github.com/criteo-forks/consul@v1.4.5-criteonogrpc/agent/config/runtime_test.go (about)

     1  package config
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"encoding/base64"
     7  	"encoding/json"
     8  	"errors"
     9  	"flag"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"net"
    13  	"os"
    14  	"path/filepath"
    15  	"reflect"
    16  	"strconv"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/hashicorp/consul/agent/consul"
    22  	"github.com/hashicorp/consul/agent/structs"
    23  	"github.com/hashicorp/consul/lib"
    24  	"github.com/hashicorp/consul/testutil"
    25  	"github.com/hashicorp/consul/types"
    26  	"github.com/pascaldekloe/goe/verify"
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  type configTest struct {
    31  	desc           string
    32  	args           []string
    33  	pre, post      func()
    34  	json, jsontail []string
    35  	hcl, hcltail   []string
    36  	skipformat     bool
    37  	privatev4      func() ([]*net.IPAddr, error)
    38  	publicv6       func() ([]*net.IPAddr, error)
    39  	patch          func(rt *RuntimeConfig)
    40  	err            string
    41  	warns          []string
    42  	hostname       func() (string, error)
    43  }
    44  
    45  // TestConfigFlagsAndEdgecases tests the command line flags and
    46  // edgecases for the config parsing. It provides a test structure which
    47  // checks for warnings on deprecated fields and flags.  These tests
    48  // should check one option at a time if possible and should use generic
    49  // values, e.g. 'a' or 1 instead of 'servicex' or 3306.
    50  
    51  func TestConfigFlagsAndEdgecases(t *testing.T) {
    52  	dataDir := testutil.TempDir(t, "consul")
    53  	defer os.RemoveAll(dataDir)
    54  
    55  	tests := []configTest{
    56  		// ------------------------------------------------------------
    57  		// cmd line flags
    58  		//
    59  
    60  		{
    61  			desc: "-advertise",
    62  			args: []string{
    63  				`-advertise=1.2.3.4`,
    64  				`-data-dir=` + dataDir,
    65  			},
    66  			patch: func(rt *RuntimeConfig) {
    67  				rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
    68  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
    69  				rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
    70  				rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
    71  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
    72  				rt.TaggedAddresses = map[string]string{
    73  					"lan": "1.2.3.4",
    74  					"wan": "1.2.3.4",
    75  				}
    76  				rt.DataDir = dataDir
    77  			},
    78  		},
    79  		{
    80  			desc: "-advertise-wan",
    81  			args: []string{
    82  				`-advertise-wan=1.2.3.4`,
    83  				`-data-dir=` + dataDir,
    84  			},
    85  			patch: func(rt *RuntimeConfig) {
    86  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
    87  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
    88  				rt.TaggedAddresses = map[string]string{
    89  					"lan": "10.0.0.1",
    90  					"wan": "1.2.3.4",
    91  				}
    92  				rt.DataDir = dataDir
    93  			},
    94  		},
    95  		{
    96  			desc: "-advertise and -advertise-wan",
    97  			args: []string{
    98  				`-advertise=1.2.3.4`,
    99  				`-advertise-wan=5.6.7.8`,
   100  				`-data-dir=` + dataDir,
   101  			},
   102  			patch: func(rt *RuntimeConfig) {
   103  				rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
   104  				rt.AdvertiseAddrWAN = ipAddr("5.6.7.8")
   105  				rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
   106  				rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
   107  				rt.SerfAdvertiseAddrWAN = tcpAddr("5.6.7.8:8302")
   108  				rt.TaggedAddresses = map[string]string{
   109  					"lan": "1.2.3.4",
   110  					"wan": "5.6.7.8",
   111  				}
   112  				rt.DataDir = dataDir
   113  			},
   114  		},
   115  		{
   116  			desc: "-bind",
   117  			args: []string{
   118  				`-bind=1.2.3.4`,
   119  				`-data-dir=` + dataDir,
   120  			},
   121  			patch: func(rt *RuntimeConfig) {
   122  				rt.BindAddr = ipAddr("1.2.3.4")
   123  				rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
   124  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
   125  				rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
   126  				rt.RPCBindAddr = tcpAddr("1.2.3.4:8300")
   127  				rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
   128  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
   129  				rt.SerfBindAddrLAN = tcpAddr("1.2.3.4:8301")
   130  				rt.SerfBindAddrWAN = tcpAddr("1.2.3.4:8302")
   131  				rt.TaggedAddresses = map[string]string{
   132  					"lan": "1.2.3.4",
   133  					"wan": "1.2.3.4",
   134  				}
   135  				rt.DataDir = dataDir
   136  			},
   137  		},
   138  		{
   139  			desc: "-bootstrap",
   140  			args: []string{
   141  				`-bootstrap`,
   142  				`-server`,
   143  				`-data-dir=` + dataDir,
   144  			},
   145  			patch: func(rt *RuntimeConfig) {
   146  				rt.Bootstrap = true
   147  				rt.ServerMode = true
   148  				rt.LeaveOnTerm = false
   149  				rt.SkipLeaveOnInt = true
   150  				rt.DataDir = dataDir
   151  			},
   152  			warns: []string{"bootstrap = true: do not enable unless necessary"},
   153  		},
   154  		{
   155  			desc: "-bootstrap-expect",
   156  			args: []string{
   157  				`-bootstrap-expect=3`,
   158  				`-server`,
   159  				`-data-dir=` + dataDir,
   160  			},
   161  			patch: func(rt *RuntimeConfig) {
   162  				rt.BootstrapExpect = 3
   163  				rt.ServerMode = true
   164  				rt.LeaveOnTerm = false
   165  				rt.SkipLeaveOnInt = true
   166  				rt.DataDir = dataDir
   167  			},
   168  			warns: []string{"bootstrap_expect > 0: expecting 3 servers"},
   169  		},
   170  		{
   171  			desc: "-client",
   172  			args: []string{
   173  				`-client=1.2.3.4`,
   174  				`-data-dir=` + dataDir,
   175  			},
   176  			patch: func(rt *RuntimeConfig) {
   177  				rt.ClientAddrs = []*net.IPAddr{ipAddr("1.2.3.4")}
   178  				rt.DNSAddrs = []net.Addr{tcpAddr("1.2.3.4:8600"), udpAddr("1.2.3.4:8600")}
   179  				rt.HTTPAddrs = []net.Addr{tcpAddr("1.2.3.4:8500")}
   180  				rt.DataDir = dataDir
   181  			},
   182  		},
   183  		{
   184  			desc: "-config-dir",
   185  			args: []string{
   186  				`-data-dir=` + dataDir,
   187  				`-config-dir`, filepath.Join(dataDir, "conf.d"),
   188  			},
   189  			patch: func(rt *RuntimeConfig) {
   190  				rt.Datacenter = "a"
   191  				rt.DataDir = dataDir
   192  			},
   193  			pre: func() {
   194  				writeFile(filepath.Join(dataDir, "conf.d/conf.json"), []byte(`{"datacenter":"a"}`))
   195  			},
   196  		},
   197  		{
   198  			desc: "-config-file json",
   199  			args: []string{
   200  				`-data-dir=` + dataDir,
   201  				`-config-file`, filepath.Join(dataDir, "conf.json"),
   202  			},
   203  			patch: func(rt *RuntimeConfig) {
   204  				rt.Datacenter = "a"
   205  				rt.DataDir = dataDir
   206  			},
   207  			pre: func() {
   208  				writeFile(filepath.Join(dataDir, "conf.json"), []byte(`{"datacenter":"a"}`))
   209  			},
   210  		},
   211  		{
   212  			desc: "-config-file hcl and json",
   213  			args: []string{
   214  				`-data-dir=` + dataDir,
   215  				`-config-file`, filepath.Join(dataDir, "conf.hcl"),
   216  				`-config-file`, filepath.Join(dataDir, "conf.json"),
   217  			},
   218  			patch: func(rt *RuntimeConfig) {
   219  				rt.Datacenter = "b"
   220  				rt.DataDir = dataDir
   221  			},
   222  			pre: func() {
   223  				writeFile(filepath.Join(dataDir, "conf.hcl"), []byte(`datacenter = "a"`))
   224  				writeFile(filepath.Join(dataDir, "conf.json"), []byte(`{"datacenter":"b"}`))
   225  			},
   226  		},
   227  		{
   228  			desc: "-data-dir empty",
   229  			args: []string{
   230  				`-data-dir=`,
   231  			},
   232  			err: "data_dir cannot be empty",
   233  		},
   234  		{
   235  			desc: "-data-dir non-directory",
   236  			args: []string{
   237  				`-data-dir=runtime_test.go`,
   238  			},
   239  			err: `data_dir "runtime_test.go" is not a directory`,
   240  		},
   241  		{
   242  			desc: "-datacenter",
   243  			args: []string{
   244  				`-datacenter=a`,
   245  				`-data-dir=` + dataDir,
   246  			},
   247  			patch: func(rt *RuntimeConfig) {
   248  				rt.Datacenter = "a"
   249  				rt.DataDir = dataDir
   250  			},
   251  		},
   252  		{
   253  			desc: "-datacenter empty",
   254  			args: []string{
   255  				`-datacenter=`,
   256  				`-data-dir=` + dataDir,
   257  			},
   258  			err: "datacenter cannot be empty",
   259  		},
   260  		{
   261  			desc: "-dev",
   262  			args: []string{
   263  				`-dev`,
   264  			},
   265  			patch: func(rt *RuntimeConfig) {
   266  				rt.AdvertiseAddrLAN = ipAddr("127.0.0.1")
   267  				rt.AdvertiseAddrWAN = ipAddr("127.0.0.1")
   268  				rt.BindAddr = ipAddr("127.0.0.1")
   269  				rt.ConnectEnabled = true
   270  				rt.DevMode = true
   271  				rt.DisableAnonymousSignature = true
   272  				rt.DisableKeyringFile = true
   273  				rt.EnableDebug = true
   274  				rt.EnableUI = true
   275  				rt.LeaveOnTerm = false
   276  				rt.LogLevel = "DEBUG"
   277  				rt.RPCAdvertiseAddr = tcpAddr("127.0.0.1:8300")
   278  				rt.RPCBindAddr = tcpAddr("127.0.0.1:8300")
   279  				rt.SerfAdvertiseAddrLAN = tcpAddr("127.0.0.1:8301")
   280  				rt.SerfAdvertiseAddrWAN = tcpAddr("127.0.0.1:8302")
   281  				rt.SerfBindAddrLAN = tcpAddr("127.0.0.1:8301")
   282  				rt.SerfBindAddrWAN = tcpAddr("127.0.0.1:8302")
   283  				rt.ServerMode = true
   284  				rt.SkipLeaveOnInt = true
   285  				rt.TaggedAddresses = map[string]string{"lan": "127.0.0.1", "wan": "127.0.0.1"}
   286  				rt.ConsulCoordinateUpdatePeriod = 100 * time.Millisecond
   287  				rt.ConsulRaftElectionTimeout = 52 * time.Millisecond
   288  				rt.ConsulRaftHeartbeatTimeout = 35 * time.Millisecond
   289  				rt.ConsulRaftLeaderLeaseTimeout = 20 * time.Millisecond
   290  				rt.GossipLANGossipInterval = 100 * time.Millisecond
   291  				rt.GossipLANProbeInterval = 100 * time.Millisecond
   292  				rt.GossipLANProbeTimeout = 100 * time.Millisecond
   293  				rt.GossipLANSuspicionMult = 3
   294  				rt.GossipWANGossipInterval = 100 * time.Millisecond
   295  				rt.GossipWANProbeInterval = 100 * time.Millisecond
   296  				rt.GossipWANProbeTimeout = 100 * time.Millisecond
   297  				rt.GossipWANSuspicionMult = 3
   298  				rt.ConsulServerHealthInterval = 10 * time.Millisecond
   299  				rt.GRPCPort = 8502
   300  				rt.GRPCAddrs = []net.Addr{tcpAddr("127.0.0.1:8502")}
   301  			},
   302  		},
   303  		{
   304  			desc: "-disable-host-node-id",
   305  			args: []string{
   306  				`-disable-host-node-id`,
   307  				`-data-dir=` + dataDir,
   308  			},
   309  			patch: func(rt *RuntimeConfig) {
   310  				rt.DisableHostNodeID = true
   311  				rt.DataDir = dataDir
   312  			},
   313  		},
   314  		{
   315  			desc: "-disable-keyring-file",
   316  			args: []string{
   317  				`-disable-keyring-file`,
   318  				`-data-dir=` + dataDir,
   319  			},
   320  			patch: func(rt *RuntimeConfig) {
   321  				rt.DisableKeyringFile = true
   322  				rt.DataDir = dataDir
   323  			},
   324  		},
   325  		{
   326  			desc: "-dns-port",
   327  			args: []string{
   328  				`-dns-port=123`,
   329  				`-data-dir=` + dataDir,
   330  			},
   331  			patch: func(rt *RuntimeConfig) {
   332  				rt.DNSPort = 123
   333  				rt.DNSAddrs = []net.Addr{tcpAddr("127.0.0.1:123"), udpAddr("127.0.0.1:123")}
   334  				rt.DataDir = dataDir
   335  			},
   336  		},
   337  		{
   338  			desc: "-domain",
   339  			args: []string{
   340  				`-domain=a`,
   341  				`-data-dir=` + dataDir,
   342  			},
   343  			patch: func(rt *RuntimeConfig) {
   344  				rt.DNSDomain = "a"
   345  				rt.DataDir = dataDir
   346  			},
   347  		},
   348  		{
   349  			desc: "-enable-script-checks",
   350  			args: []string{
   351  				`-enable-script-checks`,
   352  				`-data-dir=` + dataDir,
   353  			},
   354  			patch: func(rt *RuntimeConfig) {
   355  				rt.EnableLocalScriptChecks = true
   356  				rt.EnableRemoteScriptChecks = true
   357  				rt.DataDir = dataDir
   358  			},
   359  		},
   360  		{
   361  			desc: "-encrypt",
   362  			args: []string{
   363  				`-encrypt=i0P+gFTkLPg0h53eNYjydg==`,
   364  				`-data-dir=` + dataDir,
   365  			},
   366  			patch: func(rt *RuntimeConfig) {
   367  				rt.EncryptKey = "i0P+gFTkLPg0h53eNYjydg=="
   368  				rt.DataDir = dataDir
   369  			},
   370  		},
   371  		{
   372  			desc: "-config-format disabled, skip unknown files",
   373  			args: []string{
   374  				`-data-dir=` + dataDir,
   375  				`-config-dir`, filepath.Join(dataDir, "conf"),
   376  			},
   377  			patch: func(rt *RuntimeConfig) {
   378  				rt.Datacenter = "a"
   379  				rt.DataDir = dataDir
   380  			},
   381  			pre: func() {
   382  				writeFile(filepath.Join(dataDir, "conf", "valid.json"), []byte(`{"datacenter":"a"}`))
   383  				writeFile(filepath.Join(dataDir, "conf", "invalid.skip"), []byte(`NOPE`))
   384  			},
   385  		},
   386  		{
   387  			desc: "-config-format=json",
   388  			args: []string{
   389  				`-data-dir=` + dataDir,
   390  				`-config-format=json`,
   391  				`-config-file`, filepath.Join(dataDir, "conf"),
   392  			},
   393  			patch: func(rt *RuntimeConfig) {
   394  				rt.Datacenter = "a"
   395  				rt.DataDir = dataDir
   396  			},
   397  			pre: func() {
   398  				writeFile(filepath.Join(dataDir, "conf"), []byte(`{"datacenter":"a"}`))
   399  			},
   400  		},
   401  		{
   402  			desc: "-config-format=hcl",
   403  			args: []string{
   404  				`-data-dir=` + dataDir,
   405  				`-config-format=hcl`,
   406  				`-config-file`, filepath.Join(dataDir, "conf"),
   407  			},
   408  			patch: func(rt *RuntimeConfig) {
   409  				rt.Datacenter = "a"
   410  				rt.DataDir = dataDir
   411  			},
   412  			pre: func() {
   413  				writeFile(filepath.Join(dataDir, "conf"), []byte(`datacenter = "a"`))
   414  			},
   415  		},
   416  		{
   417  			desc: "-config-format invalid",
   418  			args: []string{
   419  				`-config-format=foobar`,
   420  			},
   421  			err: "-config-format must be either 'hcl' or 'json'",
   422  		},
   423  		{
   424  			desc: "-http-port",
   425  			args: []string{
   426  				`-http-port=123`,
   427  				`-data-dir=` + dataDir,
   428  			},
   429  			patch: func(rt *RuntimeConfig) {
   430  				rt.HTTPPort = 123
   431  				rt.HTTPAddrs = []net.Addr{tcpAddr("127.0.0.1:123")}
   432  				rt.DataDir = dataDir
   433  			},
   434  		},
   435  		{
   436  			desc: "-join",
   437  			args: []string{
   438  				`-join=a`,
   439  				`-join=b`,
   440  				`-data-dir=` + dataDir,
   441  			},
   442  			patch: func(rt *RuntimeConfig) {
   443  				rt.StartJoinAddrsLAN = []string{"a", "b"}
   444  				rt.DataDir = dataDir
   445  			},
   446  		},
   447  		{
   448  			desc: "-join-wan",
   449  			args: []string{
   450  				`-join-wan=a`,
   451  				`-join-wan=b`,
   452  				`-data-dir=` + dataDir,
   453  			},
   454  			patch: func(rt *RuntimeConfig) {
   455  				rt.StartJoinAddrsWAN = []string{"a", "b"}
   456  				rt.DataDir = dataDir
   457  			},
   458  		},
   459  		{
   460  			desc: "-log-level",
   461  			args: []string{
   462  				`-log-level=a`,
   463  				`-data-dir=` + dataDir,
   464  			},
   465  			patch: func(rt *RuntimeConfig) {
   466  				rt.LogLevel = "a"
   467  				rt.DataDir = dataDir
   468  			},
   469  		},
   470  		{
   471  			desc: "-node",
   472  			args: []string{
   473  				`-node=a`,
   474  				`-data-dir=` + dataDir,
   475  			},
   476  			patch: func(rt *RuntimeConfig) {
   477  				rt.NodeName = "a"
   478  				rt.DataDir = dataDir
   479  			},
   480  		},
   481  		{
   482  			desc: "-node-id",
   483  			args: []string{
   484  				`-node-id=a`,
   485  				`-data-dir=` + dataDir,
   486  			},
   487  			patch: func(rt *RuntimeConfig) {
   488  				rt.NodeID = "a"
   489  				rt.DataDir = dataDir
   490  			},
   491  		},
   492  		{
   493  			desc: "-node-meta",
   494  			args: []string{
   495  				`-node-meta=a:b`,
   496  				`-node-meta=c:d`,
   497  				`-data-dir=` + dataDir,
   498  			},
   499  			patch: func(rt *RuntimeConfig) {
   500  				rt.NodeMeta = map[string]string{"a": "b", "c": "d"}
   501  				rt.DataDir = dataDir
   502  			},
   503  		},
   504  		{
   505  			desc: "-non-voting-server",
   506  			args: []string{
   507  				`-non-voting-server`,
   508  				`-data-dir=` + dataDir,
   509  			},
   510  			patch: func(rt *RuntimeConfig) {
   511  				rt.NonVotingServer = true
   512  				rt.DataDir = dataDir
   513  			},
   514  		},
   515  		{
   516  			desc: "-pid-file",
   517  			args: []string{
   518  				`-pid-file=a`,
   519  				`-data-dir=` + dataDir,
   520  			},
   521  			patch: func(rt *RuntimeConfig) {
   522  				rt.PidFile = "a"
   523  				rt.DataDir = dataDir
   524  			},
   525  		},
   526  		{
   527  			desc: "-protocol",
   528  			args: []string{
   529  				`-protocol=1`,
   530  				`-data-dir=` + dataDir,
   531  			},
   532  			patch: func(rt *RuntimeConfig) {
   533  				rt.RPCProtocol = 1
   534  				rt.DataDir = dataDir
   535  			},
   536  		},
   537  		{
   538  			desc: "-raft-protocol",
   539  			args: []string{
   540  				`-raft-protocol=1`,
   541  				`-data-dir=` + dataDir,
   542  			},
   543  			patch: func(rt *RuntimeConfig) {
   544  				rt.RaftProtocol = 1
   545  				rt.DataDir = dataDir
   546  			},
   547  		},
   548  		{
   549  			desc: "-recursor",
   550  			args: []string{
   551  				`-recursor=1.2.3.4`,
   552  				`-recursor=5.6.7.8`,
   553  				`-data-dir=` + dataDir,
   554  			},
   555  			patch: func(rt *RuntimeConfig) {
   556  				rt.DNSRecursors = []string{"1.2.3.4", "5.6.7.8"}
   557  				rt.DataDir = dataDir
   558  			},
   559  		},
   560  		{
   561  			desc: "-rejoin",
   562  			args: []string{
   563  				`-rejoin`,
   564  				`-data-dir=` + dataDir,
   565  			},
   566  			patch: func(rt *RuntimeConfig) {
   567  				rt.RejoinAfterLeave = true
   568  				rt.DataDir = dataDir
   569  			},
   570  		},
   571  		{
   572  			desc: "-retry-interval",
   573  			args: []string{
   574  				`-retry-interval=5s`,
   575  				`-data-dir=` + dataDir,
   576  			},
   577  			patch: func(rt *RuntimeConfig) {
   578  				rt.RetryJoinIntervalLAN = 5 * time.Second
   579  				rt.DataDir = dataDir
   580  			},
   581  		},
   582  		{
   583  			desc: "-retry-interval-wan",
   584  			args: []string{
   585  				`-retry-interval-wan=5s`,
   586  				`-data-dir=` + dataDir,
   587  			},
   588  			patch: func(rt *RuntimeConfig) {
   589  				rt.RetryJoinIntervalWAN = 5 * time.Second
   590  				rt.DataDir = dataDir
   591  			},
   592  		},
   593  		{
   594  			desc: "-retry-join",
   595  			args: []string{
   596  				`-retry-join=a`,
   597  				`-retry-join=b`,
   598  				`-data-dir=` + dataDir,
   599  			},
   600  			patch: func(rt *RuntimeConfig) {
   601  				rt.RetryJoinLAN = []string{"a", "b"}
   602  				rt.DataDir = dataDir
   603  			},
   604  		},
   605  		{
   606  			desc: "-retry-join-wan",
   607  			args: []string{
   608  				`-retry-join-wan=a`,
   609  				`-retry-join-wan=b`,
   610  				`-data-dir=` + dataDir,
   611  			},
   612  			patch: func(rt *RuntimeConfig) {
   613  				rt.RetryJoinWAN = []string{"a", "b"}
   614  				rt.DataDir = dataDir
   615  			},
   616  		},
   617  		{
   618  			desc: "-retry-max",
   619  			args: []string{
   620  				`-retry-max=1`,
   621  				`-data-dir=` + dataDir,
   622  			},
   623  			patch: func(rt *RuntimeConfig) {
   624  				rt.RetryJoinMaxAttemptsLAN = 1
   625  				rt.DataDir = dataDir
   626  			},
   627  		},
   628  		{
   629  			desc: "-retry-max-wan",
   630  			args: []string{
   631  				`-retry-max-wan=1`,
   632  				`-data-dir=` + dataDir,
   633  			},
   634  			patch: func(rt *RuntimeConfig) {
   635  				rt.RetryJoinMaxAttemptsWAN = 1
   636  				rt.DataDir = dataDir
   637  			},
   638  		},
   639  		{
   640  			desc: "-serf-lan-bind",
   641  			args: []string{
   642  				`-serf-lan-bind=1.2.3.4`,
   643  				`-data-dir=` + dataDir,
   644  			},
   645  			patch: func(rt *RuntimeConfig) {
   646  				rt.SerfBindAddrLAN = tcpAddr("1.2.3.4:8301")
   647  				rt.DataDir = dataDir
   648  			},
   649  		},
   650  		{
   651  			desc: "-serf-lan-port",
   652  			args: []string{
   653  				`-serf-lan-port=123`,
   654  				`-data-dir=` + dataDir,
   655  			},
   656  			patch: func(rt *RuntimeConfig) {
   657  				rt.SerfPortLAN = 123
   658  				rt.SerfAdvertiseAddrLAN = tcpAddr("10.0.0.1:123")
   659  				rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:123")
   660  				rt.DataDir = dataDir
   661  			},
   662  		},
   663  		{
   664  			desc: "-serf-wan-bind",
   665  			args: []string{
   666  				`-serf-wan-bind=1.2.3.4`,
   667  				`-data-dir=` + dataDir,
   668  			},
   669  			patch: func(rt *RuntimeConfig) {
   670  				rt.SerfBindAddrWAN = tcpAddr("1.2.3.4:8302")
   671  				rt.DataDir = dataDir
   672  			},
   673  		},
   674  		{
   675  			desc: "-serf-wan-port",
   676  			args: []string{
   677  				`-serf-wan-port=123`,
   678  				`-data-dir=` + dataDir,
   679  			},
   680  			patch: func(rt *RuntimeConfig) {
   681  				rt.SerfPortWAN = 123
   682  				rt.SerfAdvertiseAddrWAN = tcpAddr("10.0.0.1:123")
   683  				rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:123")
   684  				rt.DataDir = dataDir
   685  			},
   686  		},
   687  		{
   688  			desc: "-server",
   689  			args: []string{
   690  				`-server`,
   691  				`-data-dir=` + dataDir,
   692  			},
   693  			patch: func(rt *RuntimeConfig) {
   694  				rt.ServerMode = true
   695  				rt.LeaveOnTerm = false
   696  				rt.SkipLeaveOnInt = true
   697  				rt.DataDir = dataDir
   698  			},
   699  		},
   700  		{
   701  			desc: "-server-port",
   702  			args: []string{
   703  				`-server-port=123`,
   704  				`-data-dir=` + dataDir,
   705  			},
   706  			patch: func(rt *RuntimeConfig) {
   707  				rt.ServerPort = 123
   708  				rt.RPCAdvertiseAddr = tcpAddr("10.0.0.1:123")
   709  				rt.RPCBindAddr = tcpAddr("0.0.0.0:123")
   710  				rt.DataDir = dataDir
   711  			},
   712  		},
   713  		{
   714  			desc: "-syslog",
   715  			args: []string{
   716  				`-syslog`,
   717  				`-data-dir=` + dataDir,
   718  			},
   719  			patch: func(rt *RuntimeConfig) {
   720  				rt.EnableSyslog = true
   721  				rt.DataDir = dataDir
   722  			},
   723  		},
   724  		{
   725  			desc: "-ui",
   726  			args: []string{
   727  				`-ui`,
   728  				`-data-dir=` + dataDir,
   729  			},
   730  			patch: func(rt *RuntimeConfig) {
   731  				rt.EnableUI = true
   732  				rt.DataDir = dataDir
   733  			},
   734  		},
   735  		{
   736  			desc: "-ui-dir",
   737  			args: []string{
   738  				`-ui-dir=a`,
   739  				`-data-dir=` + dataDir,
   740  			},
   741  			patch: func(rt *RuntimeConfig) {
   742  				rt.UIDir = "a"
   743  				rt.DataDir = dataDir
   744  			},
   745  		},
   746  
   747  		// ------------------------------------------------------------
   748  		// ports and addresses
   749  		//
   750  
   751  		{
   752  			desc: "bind addr any v4",
   753  			args: []string{`-data-dir=` + dataDir},
   754  			json: []string{`{ "bind_addr":"0.0.0.0" }`},
   755  			hcl:  []string{`bind_addr = "0.0.0.0"`},
   756  			patch: func(rt *RuntimeConfig) {
   757  				rt.AdvertiseAddrLAN = ipAddr("10.0.0.1")
   758  				rt.AdvertiseAddrWAN = ipAddr("10.0.0.1")
   759  				rt.BindAddr = ipAddr("0.0.0.0")
   760  				rt.RPCAdvertiseAddr = tcpAddr("10.0.0.1:8300")
   761  				rt.RPCBindAddr = tcpAddr("0.0.0.0:8300")
   762  				rt.SerfAdvertiseAddrLAN = tcpAddr("10.0.0.1:8301")
   763  				rt.SerfAdvertiseAddrWAN = tcpAddr("10.0.0.1:8302")
   764  				rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:8301")
   765  				rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:8302")
   766  				rt.TaggedAddresses = map[string]string{
   767  					"lan": "10.0.0.1",
   768  					"wan": "10.0.0.1",
   769  				}
   770  				rt.DataDir = dataDir
   771  			},
   772  		},
   773  		{
   774  			desc: "bind addr any v6",
   775  			args: []string{`-data-dir=` + dataDir},
   776  			json: []string{`{ "bind_addr":"::" }`},
   777  			hcl:  []string{`bind_addr = "::"`},
   778  			patch: func(rt *RuntimeConfig) {
   779  				rt.AdvertiseAddrLAN = ipAddr("dead:beef::1")
   780  				rt.AdvertiseAddrWAN = ipAddr("dead:beef::1")
   781  				rt.BindAddr = ipAddr("::")
   782  				rt.RPCAdvertiseAddr = tcpAddr("[dead:beef::1]:8300")
   783  				rt.RPCBindAddr = tcpAddr("[::]:8300")
   784  				rt.SerfAdvertiseAddrLAN = tcpAddr("[dead:beef::1]:8301")
   785  				rt.SerfAdvertiseAddrWAN = tcpAddr("[dead:beef::1]:8302")
   786  				rt.SerfBindAddrLAN = tcpAddr("[::]:8301")
   787  				rt.SerfBindAddrWAN = tcpAddr("[::]:8302")
   788  				rt.TaggedAddresses = map[string]string{
   789  					"lan": "dead:beef::1",
   790  					"wan": "dead:beef::1",
   791  				}
   792  				rt.DataDir = dataDir
   793  			},
   794  			publicv6: func() ([]*net.IPAddr, error) {
   795  				return []*net.IPAddr{ipAddr("dead:beef::1")}, nil
   796  			},
   797  		},
   798  		{
   799  			desc: "bind addr any and advertise set should not detect",
   800  			args: []string{`-data-dir=` + dataDir},
   801  			json: []string{`{ "bind_addr":"0.0.0.0", "advertise_addr": "1.2.3.4" }`},
   802  			hcl:  []string{`bind_addr = "0.0.0.0" advertise_addr = "1.2.3.4"`},
   803  			patch: func(rt *RuntimeConfig) {
   804  				rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
   805  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
   806  				rt.BindAddr = ipAddr("0.0.0.0")
   807  				rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
   808  				rt.RPCBindAddr = tcpAddr("0.0.0.0:8300")
   809  				rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
   810  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
   811  				rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:8301")
   812  				rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:8302")
   813  				rt.TaggedAddresses = map[string]string{
   814  					"lan": "1.2.3.4",
   815  					"wan": "1.2.3.4",
   816  				}
   817  				rt.DataDir = dataDir
   818  			},
   819  			privatev4: func() ([]*net.IPAddr, error) {
   820  				return nil, fmt.Errorf("should not detect advertise_addr")
   821  			},
   822  		},
   823  		{
   824  			desc: "client addr and ports == 0",
   825  			args: []string{`-data-dir=` + dataDir},
   826  			json: []string{`{
   827  					"client_addr":"0.0.0.0",
   828  					"ports":{}
   829  				}`},
   830  			hcl: []string{`
   831  					client_addr = "0.0.0.0"
   832  					ports {}
   833  				`},
   834  			patch: func(rt *RuntimeConfig) {
   835  				rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
   836  				rt.DNSAddrs = []net.Addr{tcpAddr("0.0.0.0:8600"), udpAddr("0.0.0.0:8600")}
   837  				rt.HTTPAddrs = []net.Addr{tcpAddr("0.0.0.0:8500")}
   838  				rt.DataDir = dataDir
   839  			},
   840  		},
   841  		{
   842  			desc: "client addr and ports < 0",
   843  			args: []string{`-data-dir=` + dataDir},
   844  			json: []string{`{
   845  					"client_addr":"0.0.0.0",
   846  					"ports": { "dns":-1, "http":-2, "https":-3, "grpc":-4 }
   847  				}`},
   848  			hcl: []string{`
   849  					client_addr = "0.0.0.0"
   850  					ports { dns = -1 http = -2 https = -3 grpc = -4 }
   851  				`},
   852  			patch: func(rt *RuntimeConfig) {
   853  				rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
   854  				rt.DNSPort = -1
   855  				rt.DNSAddrs = nil
   856  				rt.HTTPPort = -1
   857  				rt.HTTPAddrs = nil
   858  				// HTTPS and gRPC default to disabled so shouldn't be different from
   859  				// default rt.
   860  				rt.DataDir = dataDir
   861  			},
   862  		},
   863  		{
   864  			desc: "client addr and ports > 0",
   865  			args: []string{`-data-dir=` + dataDir},
   866  			json: []string{`{
   867  					"client_addr":"0.0.0.0",
   868  					"ports":{ "dns": 1, "http": 2, "https": 3, "grpc": 4 }
   869  				}`},
   870  			hcl: []string{`
   871  					client_addr = "0.0.0.0"
   872  					ports { dns = 1 http = 2 https = 3 grpc = 4 }
   873  				`},
   874  			patch: func(rt *RuntimeConfig) {
   875  				rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
   876  				rt.DNSPort = 1
   877  				rt.DNSAddrs = []net.Addr{tcpAddr("0.0.0.0:1"), udpAddr("0.0.0.0:1")}
   878  				rt.HTTPPort = 2
   879  				rt.HTTPAddrs = []net.Addr{tcpAddr("0.0.0.0:2")}
   880  				rt.HTTPSPort = 3
   881  				rt.HTTPSAddrs = []net.Addr{tcpAddr("0.0.0.0:3")}
   882  				rt.GRPCPort = 4
   883  				rt.GRPCAddrs = []net.Addr{tcpAddr("0.0.0.0:4")}
   884  				rt.DataDir = dataDir
   885  			},
   886  		},
   887  
   888  		{
   889  			desc: "client addr, addresses and ports == 0",
   890  			args: []string{`-data-dir=` + dataDir},
   891  			json: []string{`{
   892  					"client_addr":"0.0.0.0",
   893  					"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3", "grpc": "4.4.4.4" },
   894  					"ports":{}
   895  				}`},
   896  			hcl: []string{`
   897  					client_addr = "0.0.0.0"
   898  					addresses = { dns = "1.1.1.1" http = "2.2.2.2" https = "3.3.3.3" grpc = "4.4.4.4" }
   899  					ports {}
   900  				`},
   901  			patch: func(rt *RuntimeConfig) {
   902  				rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
   903  				rt.DNSAddrs = []net.Addr{tcpAddr("1.1.1.1:8600"), udpAddr("1.1.1.1:8600")}
   904  				rt.HTTPAddrs = []net.Addr{tcpAddr("2.2.2.2:8500")}
   905  				// HTTPS and gRPC default to disabled so shouldn't be different from
   906  				// default rt.
   907  				rt.DataDir = dataDir
   908  			},
   909  		},
   910  		{
   911  			desc: "client addr, addresses and ports < 0",
   912  			args: []string{`-data-dir=` + dataDir},
   913  			json: []string{`{
   914  					"client_addr":"0.0.0.0",
   915  					"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3", "grpc": "4.4.4.4" },
   916  					"ports": { "dns":-1, "http":-2, "https":-3, "grpc":-4 }
   917  				}`},
   918  			hcl: []string{`
   919  					client_addr = "0.0.0.0"
   920  					addresses = { dns = "1.1.1.1" http = "2.2.2.2" https = "3.3.3.3" grpc = "4.4.4.4" }
   921  					ports { dns = -1 http = -2 https = -3 grpc = -4 }
   922  				`},
   923  			patch: func(rt *RuntimeConfig) {
   924  				rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
   925  				rt.DNSPort = -1
   926  				rt.DNSAddrs = nil
   927  				rt.HTTPPort = -1
   928  				rt.HTTPAddrs = nil
   929  				// HTTPS and gRPC default to disabled so shouldn't be different from
   930  				// default rt.
   931  				rt.DataDir = dataDir
   932  			},
   933  		},
   934  		{
   935  			desc: "client addr, addresses and ports",
   936  			args: []string{`-data-dir=` + dataDir},
   937  			json: []string{`{
   938  					"client_addr": "0.0.0.0",
   939  					"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3", "grpc": "4.4.4.4" },
   940  					"ports":{ "dns":1, "http":2, "https":3, "grpc":4 }
   941  				}`},
   942  			hcl: []string{`
   943  					client_addr = "0.0.0.0"
   944  					addresses = { dns = "1.1.1.1" http = "2.2.2.2" https = "3.3.3.3" grpc = "4.4.4.4" }
   945  					ports { dns = 1 http = 2 https = 3 grpc = 4 }
   946  				`},
   947  			patch: func(rt *RuntimeConfig) {
   948  				rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
   949  				rt.DNSPort = 1
   950  				rt.DNSAddrs = []net.Addr{tcpAddr("1.1.1.1:1"), udpAddr("1.1.1.1:1")}
   951  				rt.HTTPPort = 2
   952  				rt.HTTPAddrs = []net.Addr{tcpAddr("2.2.2.2:2")}
   953  				rt.HTTPSPort = 3
   954  				rt.HTTPSAddrs = []net.Addr{tcpAddr("3.3.3.3:3")}
   955  				rt.GRPCPort = 4
   956  				rt.GRPCAddrs = []net.Addr{tcpAddr("4.4.4.4:4")}
   957  				rt.DataDir = dataDir
   958  			},
   959  		},
   960  		{
   961  			desc: "client template and ports",
   962  			args: []string{`-data-dir=` + dataDir},
   963  			json: []string{`{
   964  					"client_addr": "{{ printf \"1.2.3.4 2001:db8::1\" }}",
   965  					"ports":{ "dns":1, "http":2, "https":3, "grpc":4 }
   966  				}`},
   967  			hcl: []string{`
   968  					client_addr = "{{ printf \"1.2.3.4 2001:db8::1\" }}"
   969  					ports { dns = 1 http = 2 https = 3 grpc = 4 }
   970  				`},
   971  			patch: func(rt *RuntimeConfig) {
   972  				rt.ClientAddrs = []*net.IPAddr{ipAddr("1.2.3.4"), ipAddr("2001:db8::1")}
   973  				rt.DNSPort = 1
   974  				rt.DNSAddrs = []net.Addr{tcpAddr("1.2.3.4:1"), tcpAddr("[2001:db8::1]:1"), udpAddr("1.2.3.4:1"), udpAddr("[2001:db8::1]:1")}
   975  				rt.HTTPPort = 2
   976  				rt.HTTPAddrs = []net.Addr{tcpAddr("1.2.3.4:2"), tcpAddr("[2001:db8::1]:2")}
   977  				rt.HTTPSPort = 3
   978  				rt.HTTPSAddrs = []net.Addr{tcpAddr("1.2.3.4:3"), tcpAddr("[2001:db8::1]:3")}
   979  				rt.GRPCPort = 4
   980  				rt.GRPCAddrs = []net.Addr{tcpAddr("1.2.3.4:4"), tcpAddr("[2001:db8::1]:4")}
   981  				rt.DataDir = dataDir
   982  			},
   983  		},
   984  		{
   985  			desc: "client, address template and ports",
   986  			args: []string{`-data-dir=` + dataDir},
   987  			json: []string{`{
   988  					"client_addr": "{{ printf \"1.2.3.4 2001:db8::1\" }}",
   989  					"addresses": {
   990  						"dns": "{{ printf \"1.1.1.1 2001:db8::10 \" }}",
   991  						"http": "{{ printf \"2.2.2.2 unix://http 2001:db8::20 \" }}",
   992  						"https": "{{ printf \"3.3.3.3 unix://https 2001:db8::30 \" }}",
   993  						"grpc": "{{ printf \"4.4.4.4 unix://grpc 2001:db8::40 \" }}"
   994  					},
   995  					"ports":{ "dns":1, "http":2, "https":3, "grpc":4 }
   996  				}`},
   997  			hcl: []string{`
   998  					client_addr = "{{ printf \"1.2.3.4 2001:db8::1\" }}"
   999  					addresses = {
  1000  						dns = "{{ printf \"1.1.1.1 2001:db8::10 \" }}"
  1001  						http = "{{ printf \"2.2.2.2 unix://http 2001:db8::20 \" }}"
  1002  						https = "{{ printf \"3.3.3.3 unix://https 2001:db8::30 \" }}"
  1003  						grpc = "{{ printf \"4.4.4.4 unix://grpc 2001:db8::40 \" }}"
  1004  					}
  1005  					ports { dns = 1 http = 2 https = 3 grpc = 4 }
  1006  				`},
  1007  			patch: func(rt *RuntimeConfig) {
  1008  				rt.ClientAddrs = []*net.IPAddr{ipAddr("1.2.3.4"), ipAddr("2001:db8::1")}
  1009  				rt.DNSPort = 1
  1010  				rt.DNSAddrs = []net.Addr{tcpAddr("1.1.1.1:1"), tcpAddr("[2001:db8::10]:1"), udpAddr("1.1.1.1:1"), udpAddr("[2001:db8::10]:1")}
  1011  				rt.HTTPPort = 2
  1012  				rt.HTTPAddrs = []net.Addr{tcpAddr("2.2.2.2:2"), unixAddr("unix://http"), tcpAddr("[2001:db8::20]:2")}
  1013  				rt.HTTPSPort = 3
  1014  				rt.HTTPSAddrs = []net.Addr{tcpAddr("3.3.3.3:3"), unixAddr("unix://https"), tcpAddr("[2001:db8::30]:3")}
  1015  				rt.GRPCPort = 4
  1016  				rt.GRPCAddrs = []net.Addr{tcpAddr("4.4.4.4:4"), unixAddr("unix://grpc"), tcpAddr("[2001:db8::40]:4")}
  1017  				rt.DataDir = dataDir
  1018  			},
  1019  		},
  1020  		{
  1021  			desc: "advertise address lan template",
  1022  			args: []string{`-data-dir=` + dataDir},
  1023  			json: []string{`{ "advertise_addr": "{{ printf \"1.2.3.4\" }}" }`},
  1024  			hcl:  []string{`advertise_addr = "{{ printf \"1.2.3.4\" }}"`},
  1025  			patch: func(rt *RuntimeConfig) {
  1026  				rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
  1027  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
  1028  				rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
  1029  				rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
  1030  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
  1031  				rt.TaggedAddresses = map[string]string{
  1032  					"lan": "1.2.3.4",
  1033  					"wan": "1.2.3.4",
  1034  				}
  1035  				rt.DataDir = dataDir
  1036  			},
  1037  		},
  1038  		{
  1039  			desc: "advertise address wan template",
  1040  			args: []string{`-data-dir=` + dataDir},
  1041  			json: []string{`{ "advertise_addr_wan": "{{ printf \"1.2.3.4\" }}" }`},
  1042  			hcl:  []string{`advertise_addr_wan = "{{ printf \"1.2.3.4\" }}"`},
  1043  			patch: func(rt *RuntimeConfig) {
  1044  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
  1045  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
  1046  				rt.TaggedAddresses = map[string]string{
  1047  					"lan": "10.0.0.1",
  1048  					"wan": "1.2.3.4",
  1049  				}
  1050  				rt.DataDir = dataDir
  1051  			},
  1052  		},
  1053  		{
  1054  			desc: "advertise address lan with ports",
  1055  			args: []string{`-data-dir=` + dataDir},
  1056  			json: []string{`{
  1057  				"ports": {
  1058  					"server": 1000,
  1059  					"serf_lan": 2000,
  1060  					"serf_wan": 3000
  1061  				},
  1062  				"advertise_addr": "1.2.3.4"
  1063  			}`},
  1064  			hcl: []string{`
  1065  				ports {
  1066  					server = 1000
  1067  					serf_lan = 2000
  1068  					serf_wan = 3000
  1069  				}
  1070  				advertise_addr = "1.2.3.4"
  1071  			`},
  1072  			patch: func(rt *RuntimeConfig) {
  1073  				rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
  1074  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
  1075  				rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:1000")
  1076  				rt.RPCBindAddr = tcpAddr("0.0.0.0:1000")
  1077  				rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:2000")
  1078  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:3000")
  1079  				rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:2000")
  1080  				rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:3000")
  1081  				rt.SerfPortLAN = 2000
  1082  				rt.SerfPortWAN = 3000
  1083  				rt.ServerPort = 1000
  1084  				rt.TaggedAddresses = map[string]string{
  1085  					"lan": "1.2.3.4",
  1086  					"wan": "1.2.3.4",
  1087  				}
  1088  				rt.DataDir = dataDir
  1089  			},
  1090  		},
  1091  		{
  1092  			desc: "advertise address wan with ports",
  1093  			args: []string{`-data-dir=` + dataDir},
  1094  			json: []string{`{
  1095  				"ports": {
  1096  					"server": 1000,
  1097  					"serf_lan": 2000,
  1098  					"serf_wan": 3000
  1099  				},
  1100  				"advertise_addr_wan": "1.2.3.4"
  1101  			}`},
  1102  			hcl: []string{`
  1103  				ports {
  1104  					server = 1000
  1105  					serf_lan = 2000
  1106  					serf_wan = 3000
  1107  				}
  1108  				advertise_addr_wan = "1.2.3.4"
  1109  			`},
  1110  			patch: func(rt *RuntimeConfig) {
  1111  				rt.AdvertiseAddrLAN = ipAddr("10.0.0.1")
  1112  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
  1113  				rt.RPCAdvertiseAddr = tcpAddr("10.0.0.1:1000")
  1114  				rt.RPCBindAddr = tcpAddr("0.0.0.0:1000")
  1115  				rt.SerfAdvertiseAddrLAN = tcpAddr("10.0.0.1:2000")
  1116  				rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:3000")
  1117  				rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:2000")
  1118  				rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:3000")
  1119  				rt.SerfPortLAN = 2000
  1120  				rt.SerfPortWAN = 3000
  1121  				rt.ServerPort = 1000
  1122  				rt.TaggedAddresses = map[string]string{
  1123  					"lan": "10.0.0.1",
  1124  					"wan": "1.2.3.4",
  1125  				}
  1126  				rt.DataDir = dataDir
  1127  			},
  1128  		},
  1129  		{
  1130  			desc: "allow disabling serf wan port",
  1131  			args: []string{`-data-dir=` + dataDir},
  1132  			json: []string{`{
  1133  				"ports": {
  1134  					"serf_wan": -1
  1135  				},
  1136  				"advertise_addr_wan": "1.2.3.4"
  1137  			}`},
  1138  			hcl: []string{`
  1139  				ports {
  1140  					serf_wan = -1
  1141  				}
  1142  				advertise_addr_wan = "1.2.3.4"
  1143  			`},
  1144  			patch: func(rt *RuntimeConfig) {
  1145  				rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
  1146  				rt.SerfAdvertiseAddrWAN = nil
  1147  				rt.SerfBindAddrWAN = nil
  1148  				rt.TaggedAddresses = map[string]string{
  1149  					"lan": "10.0.0.1",
  1150  					"wan": "1.2.3.4",
  1151  				}
  1152  				rt.DataDir = dataDir
  1153  				rt.SerfPortWAN = -1
  1154  			},
  1155  		},
  1156  		{
  1157  			desc: "serf bind address lan template",
  1158  			args: []string{`-data-dir=` + dataDir},
  1159  			json: []string{`{ "serf_lan": "{{ printf \"1.2.3.4\" }}" }`},
  1160  			hcl:  []string{`serf_lan = "{{ printf \"1.2.3.4\" }}"`},
  1161  			patch: func(rt *RuntimeConfig) {
  1162  				rt.SerfBindAddrLAN = tcpAddr("1.2.3.4:8301")
  1163  				rt.DataDir = dataDir
  1164  			},
  1165  		},
  1166  		{
  1167  			desc: "serf bind address wan template",
  1168  			args: []string{`-data-dir=` + dataDir},
  1169  			json: []string{`{ "serf_wan": "{{ printf \"1.2.3.4\" }}" }`},
  1170  			hcl:  []string{`serf_wan = "{{ printf \"1.2.3.4\" }}"`},
  1171  			patch: func(rt *RuntimeConfig) {
  1172  				rt.SerfBindAddrWAN = tcpAddr("1.2.3.4:8302")
  1173  				rt.DataDir = dataDir
  1174  			},
  1175  		},
  1176  		{
  1177  			desc: "dns recursor templates with deduplication",
  1178  			args: []string{`-data-dir=` + dataDir},
  1179  			json: []string{`{ "recursors": [ "{{ printf \"5.6.7.8:9999\" }}", "{{ printf \"1.2.3.4\" }}", "{{ printf \"5.6.7.8:9999\" }}" ] }`},
  1180  			hcl:  []string{`recursors = [ "{{ printf \"5.6.7.8:9999\" }}", "{{ printf \"1.2.3.4\" }}", "{{ printf \"5.6.7.8:9999\" }}" ] `},
  1181  			patch: func(rt *RuntimeConfig) {
  1182  				rt.DNSRecursors = []string{"5.6.7.8:9999", "1.2.3.4"}
  1183  				rt.DataDir = dataDir
  1184  			},
  1185  		},
  1186  		{
  1187  			desc: "start_join address template",
  1188  			args: []string{`-data-dir=` + dataDir},
  1189  			json: []string{`{ "start_join": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
  1190  			hcl:  []string{`start_join = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
  1191  			patch: func(rt *RuntimeConfig) {
  1192  				rt.StartJoinAddrsLAN = []string{"1.2.3.4", "4.3.2.1"}
  1193  				rt.DataDir = dataDir
  1194  			},
  1195  		},
  1196  		{
  1197  			desc: "start_join_wan address template",
  1198  			args: []string{`-data-dir=` + dataDir},
  1199  			json: []string{`{ "start_join_wan": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
  1200  			hcl:  []string{`start_join_wan = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
  1201  			patch: func(rt *RuntimeConfig) {
  1202  				rt.StartJoinAddrsWAN = []string{"1.2.3.4", "4.3.2.1"}
  1203  				rt.DataDir = dataDir
  1204  			},
  1205  		},
  1206  		{
  1207  			desc: "retry_join address template",
  1208  			args: []string{`-data-dir=` + dataDir},
  1209  			json: []string{`{ "retry_join": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
  1210  			hcl:  []string{`retry_join = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
  1211  			patch: func(rt *RuntimeConfig) {
  1212  				rt.RetryJoinLAN = []string{"1.2.3.4", "4.3.2.1"}
  1213  				rt.DataDir = dataDir
  1214  			},
  1215  		},
  1216  		{
  1217  			desc: "retry_join_wan address template",
  1218  			args: []string{`-data-dir=` + dataDir},
  1219  			json: []string{`{ "retry_join_wan": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
  1220  			hcl:  []string{`retry_join_wan = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
  1221  			patch: func(rt *RuntimeConfig) {
  1222  				rt.RetryJoinWAN = []string{"1.2.3.4", "4.3.2.1"}
  1223  				rt.DataDir = dataDir
  1224  			},
  1225  		},
  1226  
  1227  		// ------------------------------------------------------------
  1228  		// precedence rules
  1229  		//
  1230  
  1231  		{
  1232  			desc: "precedence: merge order",
  1233  			args: []string{`-data-dir=` + dataDir},
  1234  			json: []string{
  1235  				`{
  1236  						"bootstrap": true,
  1237  						"bootstrap_expect": 1,
  1238  						"datacenter": "a",
  1239  						"start_join": ["a", "b"],
  1240  						"node_meta": {"a":"b"}
  1241  					}`,
  1242  				`{
  1243  						"bootstrap": false,
  1244  						"bootstrap_expect": 0,
  1245  						"datacenter":"b",
  1246  						"start_join": ["c", "d"],
  1247  						"node_meta": {"a":"c"}
  1248  					}`,
  1249  			},
  1250  			hcl: []string{
  1251  				`
  1252  					bootstrap = true
  1253  					bootstrap_expect = 1
  1254  					datacenter = "a"
  1255  					start_join = ["a", "b"]
  1256  					node_meta = { "a" = "b" }
  1257  					`,
  1258  				`
  1259  					bootstrap = false
  1260  					bootstrap_expect = 0
  1261  					datacenter = "b"
  1262  					start_join = ["c", "d"]
  1263  					node_meta = { "a" = "c" }
  1264  					`,
  1265  			},
  1266  			patch: func(rt *RuntimeConfig) {
  1267  				rt.Bootstrap = false
  1268  				rt.BootstrapExpect = 0
  1269  				rt.Datacenter = "b"
  1270  				rt.StartJoinAddrsLAN = []string{"a", "b", "c", "d"}
  1271  				rt.NodeMeta = map[string]string{"a": "c"}
  1272  				rt.DataDir = dataDir
  1273  			},
  1274  		},
  1275  		{
  1276  			desc: "precedence: flag before file",
  1277  			json: []string{
  1278  				`{
  1279  						"advertise_addr": "1.2.3.4",
  1280  						"advertise_addr_wan": "5.6.7.8",
  1281  						"bootstrap":true,
  1282  						"bootstrap_expect": 3,
  1283  						"datacenter":"a",
  1284  						"node_meta": {"a":"b"},
  1285  						"recursors":["1.2.3.5", "5.6.7.9"],
  1286  						"serf_lan": "a",
  1287  						"serf_wan": "a",
  1288  						"start_join":["a", "b"]
  1289  					}`,
  1290  			},
  1291  			hcl: []string{
  1292  				`
  1293  					advertise_addr = "1.2.3.4"
  1294  					advertise_addr_wan = "5.6.7.8"
  1295  					bootstrap = true
  1296  					bootstrap_expect = 3
  1297  					datacenter = "a"
  1298  					node_meta = { "a" = "b" }
  1299  					recursors = ["1.2.3.5", "5.6.7.9"]
  1300  					serf_lan = "a"
  1301  					serf_wan = "a"
  1302  					start_join = ["a", "b"]
  1303  					`,
  1304  			},
  1305  			args: []string{
  1306  				`-advertise=1.1.1.1`,
  1307  				`-advertise-wan=2.2.2.2`,
  1308  				`-bootstrap=false`,
  1309  				`-bootstrap-expect=0`,
  1310  				`-datacenter=b`,
  1311  				`-data-dir=` + dataDir,
  1312  				`-join`, `c`, `-join=d`,
  1313  				`-node-meta=a:c`,
  1314  				`-recursor`, `1.2.3.6`, `-recursor=5.6.7.10`,
  1315  				`-serf-lan-bind=3.3.3.3`,
  1316  				`-serf-wan-bind=4.4.4.4`,
  1317  			},
  1318  			patch: func(rt *RuntimeConfig) {
  1319  				rt.AdvertiseAddrLAN = ipAddr("1.1.1.1")
  1320  				rt.AdvertiseAddrWAN = ipAddr("2.2.2.2")
  1321  				rt.RPCAdvertiseAddr = tcpAddr("1.1.1.1:8300")
  1322  				rt.SerfAdvertiseAddrLAN = tcpAddr("1.1.1.1:8301")
  1323  				rt.SerfAdvertiseAddrWAN = tcpAddr("2.2.2.2:8302")
  1324  				rt.Datacenter = "b"
  1325  				rt.DNSRecursors = []string{"1.2.3.6", "5.6.7.10", "1.2.3.5", "5.6.7.9"}
  1326  				rt.NodeMeta = map[string]string{"a": "c"}
  1327  				rt.SerfBindAddrLAN = tcpAddr("3.3.3.3:8301")
  1328  				rt.SerfBindAddrWAN = tcpAddr("4.4.4.4:8302")
  1329  				rt.StartJoinAddrsLAN = []string{"c", "d", "a", "b"}
  1330  				rt.TaggedAddresses = map[string]string{
  1331  					"lan": "1.1.1.1",
  1332  					"wan": "2.2.2.2",
  1333  				}
  1334  				rt.DataDir = dataDir
  1335  			},
  1336  		},
  1337  
  1338  		// ------------------------------------------------------------
  1339  		// transformations
  1340  		//
  1341  
  1342  		{
  1343  			desc: "raft performance scaling",
  1344  			args: []string{`-data-dir=` + dataDir},
  1345  			json: []string{`{ "performance": { "raft_multiplier": 9} }`},
  1346  			hcl:  []string{`performance = { raft_multiplier=9 }`},
  1347  			patch: func(rt *RuntimeConfig) {
  1348  				rt.ConsulRaftElectionTimeout = 9 * 1000 * time.Millisecond
  1349  				rt.ConsulRaftHeartbeatTimeout = 9 * 1000 * time.Millisecond
  1350  				rt.ConsulRaftLeaderLeaseTimeout = 9 * 500 * time.Millisecond
  1351  				rt.DataDir = dataDir
  1352  			},
  1353  		},
  1354  
  1355  		// ------------------------------------------------------------
  1356  		// validations
  1357  		//
  1358  
  1359  		{
  1360  			desc: "invalid input",
  1361  			args: []string{`-data-dir=` + dataDir},
  1362  			json: []string{`this is not JSON`},
  1363  			hcl:  []string{`*** 0123 this is not HCL`},
  1364  			err:  "Error parsing",
  1365  		},
  1366  		{
  1367  			desc: "datacenter is lower-cased",
  1368  			args: []string{`-data-dir=` + dataDir},
  1369  			json: []string{`{ "datacenter": "A" }`},
  1370  			hcl:  []string{`datacenter = "A"`},
  1371  			patch: func(rt *RuntimeConfig) {
  1372  				rt.Datacenter = "a"
  1373  				rt.DataDir = dataDir
  1374  			},
  1375  		},
  1376  		{
  1377  			desc: "acl_datacenter is lower-cased",
  1378  			args: []string{`-data-dir=` + dataDir},
  1379  			json: []string{`{ "acl_datacenter": "A" }`},
  1380  			hcl:  []string{`acl_datacenter = "A"`},
  1381  			patch: func(rt *RuntimeConfig) {
  1382  				rt.ACLsEnabled = true
  1383  				rt.ACLDatacenter = "a"
  1384  				rt.DataDir = dataDir
  1385  				rt.PrimaryDatacenter = "a"
  1386  			},
  1387  			warns: []string{`The 'acl_datacenter' field is deprecated. Use the 'primary_datacenter' field instead.`},
  1388  		},
  1389  		{
  1390  			desc: "acl_replication_token enables acl replication",
  1391  			args: []string{`-data-dir=` + dataDir},
  1392  			json: []string{`{ "acl_replication_token": "a" }`},
  1393  			hcl:  []string{`acl_replication_token = "a"`},
  1394  			patch: func(rt *RuntimeConfig) {
  1395  				rt.ACLReplicationToken = "a"
  1396  				rt.ACLTokenReplication = true
  1397  				rt.DataDir = dataDir
  1398  			},
  1399  		},
  1400  		{
  1401  			desc: "advertise address detect fails v4",
  1402  			args: []string{`-data-dir=` + dataDir},
  1403  			json: []string{`{ "bind_addr": "0.0.0.0"}`},
  1404  			hcl:  []string{`bind_addr = "0.0.0.0"`},
  1405  			privatev4: func() ([]*net.IPAddr, error) {
  1406  				return nil, errors.New("some error")
  1407  			},
  1408  			err: "Error detecting private IPv4 address: some error",
  1409  		},
  1410  		{
  1411  			desc: "advertise address detect none v4",
  1412  			args: []string{`-data-dir=` + dataDir},
  1413  			json: []string{`{ "bind_addr": "0.0.0.0"}`},
  1414  			hcl:  []string{`bind_addr = "0.0.0.0"`},
  1415  			privatev4: func() ([]*net.IPAddr, error) {
  1416  				return nil, nil
  1417  			},
  1418  			err: "No private IPv4 address found",
  1419  		},
  1420  		{
  1421  			desc: "advertise address detect multiple v4",
  1422  			args: []string{`-data-dir=` + dataDir},
  1423  			json: []string{`{ "bind_addr": "0.0.0.0"}`},
  1424  			hcl:  []string{`bind_addr = "0.0.0.0"`},
  1425  			privatev4: func() ([]*net.IPAddr, error) {
  1426  				return []*net.IPAddr{ipAddr("1.1.1.1"), ipAddr("2.2.2.2")}, nil
  1427  			},
  1428  			err: "Multiple private IPv4 addresses found. Please configure one",
  1429  		},
  1430  		{
  1431  			desc: "advertise address detect fails v6",
  1432  			args: []string{`-data-dir=` + dataDir},
  1433  			json: []string{`{ "bind_addr": "::"}`},
  1434  			hcl:  []string{`bind_addr = "::"`},
  1435  			publicv6: func() ([]*net.IPAddr, error) {
  1436  				return nil, errors.New("some error")
  1437  			},
  1438  			err: "Error detecting public IPv6 address: some error",
  1439  		},
  1440  		{
  1441  			desc: "advertise address detect none v6",
  1442  			args: []string{`-data-dir=` + dataDir},
  1443  			json: []string{`{ "bind_addr": "::"}`},
  1444  			hcl:  []string{`bind_addr = "::"`},
  1445  			publicv6: func() ([]*net.IPAddr, error) {
  1446  				return nil, nil
  1447  			},
  1448  			err: "No public IPv6 address found",
  1449  		},
  1450  		{
  1451  			desc: "advertise address detect multiple v6",
  1452  			args: []string{`-data-dir=` + dataDir},
  1453  			json: []string{`{ "bind_addr": "::"}`},
  1454  			hcl:  []string{`bind_addr = "::"`},
  1455  			publicv6: func() ([]*net.IPAddr, error) {
  1456  				return []*net.IPAddr{ipAddr("dead:beef::1"), ipAddr("dead:beef::2")}, nil
  1457  			},
  1458  			err: "Multiple public IPv6 addresses found. Please configure one",
  1459  		},
  1460  		{
  1461  			desc:     "ae_interval invalid == 0",
  1462  			args:     []string{`-data-dir=` + dataDir},
  1463  			jsontail: []string{`{ "ae_interval": "0s" }`},
  1464  			hcltail:  []string{`ae_interval = "0s"`},
  1465  			err:      `ae_interval cannot be 0s. Must be positive`,
  1466  		},
  1467  		{
  1468  			desc:     "ae_interval invalid < 0",
  1469  			args:     []string{`-data-dir=` + dataDir},
  1470  			jsontail: []string{`{ "ae_interval": "-1s" }`},
  1471  			hcltail:  []string{`ae_interval = "-1s"`},
  1472  			err:      `ae_interval cannot be -1s. Must be positive`,
  1473  		},
  1474  		{
  1475  			desc: "acl_datacenter invalid",
  1476  			args: []string{
  1477  				`-datacenter=a`,
  1478  				`-data-dir=` + dataDir,
  1479  			},
  1480  			json:  []string{`{ "acl_datacenter": "%" }`},
  1481  			hcl:   []string{`acl_datacenter = "%"`},
  1482  			err:   `acl_datacenter cannot be "%". Please use only [a-z0-9-_]`,
  1483  			warns: []string{`The 'acl_datacenter' field is deprecated. Use the 'primary_datacenter' field instead.`},
  1484  		},
  1485  		{
  1486  			desc: "autopilot.max_trailing_logs invalid",
  1487  			args: []string{
  1488  				`-datacenter=a`,
  1489  				`-data-dir=` + dataDir,
  1490  			},
  1491  			json: []string{`{ "autopilot": { "max_trailing_logs": -1 } }`},
  1492  			hcl:  []string{`autopilot = { max_trailing_logs = -1 }`},
  1493  			err:  "autopilot.max_trailing_logs cannot be -1. Must be greater than or equal to zero",
  1494  		},
  1495  		{
  1496  			desc: "bind_addr cannot be empty",
  1497  			args: []string{`-data-dir=` + dataDir},
  1498  			json: []string{`{ "bind_addr": "" }`},
  1499  			hcl:  []string{`bind_addr = ""`},
  1500  			err:  "bind_addr cannot be empty",
  1501  		},
  1502  		{
  1503  			desc: "bind_addr does not allow multiple addresses",
  1504  			args: []string{`-data-dir=` + dataDir},
  1505  			json: []string{`{ "bind_addr": "1.1.1.1 2.2.2.2" }`},
  1506  			hcl:  []string{`bind_addr = "1.1.1.1 2.2.2.2"`},
  1507  			err:  "bind_addr cannot contain multiple addresses",
  1508  		},
  1509  		{
  1510  			desc: "bind_addr cannot be a unix socket",
  1511  			args: []string{`-data-dir=` + dataDir},
  1512  			json: []string{`{ "bind_addr": "unix:///foo" }`},
  1513  			hcl:  []string{`bind_addr = "unix:///foo"`},
  1514  			err:  "bind_addr cannot be a unix socket",
  1515  		},
  1516  		{
  1517  			desc: "bootstrap without server",
  1518  			args: []string{
  1519  				`-datacenter=a`,
  1520  				`-data-dir=` + dataDir,
  1521  			},
  1522  			json: []string{`{ "bootstrap": true }`},
  1523  			hcl:  []string{`bootstrap = true`},
  1524  			err:  "'bootstrap = true' requires 'server = true'",
  1525  		},
  1526  		{
  1527  			desc: "bootstrap-expect without server",
  1528  			args: []string{
  1529  				`-datacenter=a`,
  1530  				`-data-dir=` + dataDir,
  1531  			},
  1532  			json: []string{`{ "bootstrap_expect": 3 }`},
  1533  			hcl:  []string{`bootstrap_expect = 3`},
  1534  			err:  "'bootstrap_expect > 0' requires 'server = true'",
  1535  		},
  1536  		{
  1537  			desc: "bootstrap-expect invalid",
  1538  			args: []string{
  1539  				`-datacenter=a`,
  1540  				`-data-dir=` + dataDir,
  1541  			},
  1542  			json: []string{`{ "bootstrap_expect": -1 }`},
  1543  			hcl:  []string{`bootstrap_expect = -1`},
  1544  			err:  "bootstrap_expect cannot be -1. Must be greater than or equal to zero",
  1545  		},
  1546  		{
  1547  			desc: "bootstrap-expect and dev mode",
  1548  			args: []string{
  1549  				`-dev`,
  1550  				`-datacenter=a`,
  1551  				`-data-dir=` + dataDir,
  1552  			},
  1553  			json: []string{`{ "bootstrap_expect": 3, "server": true }`},
  1554  			hcl:  []string{`bootstrap_expect = 3 server = true`},
  1555  			err:  "'bootstrap_expect > 0' not allowed in dev mode",
  1556  		},
  1557  		{
  1558  			desc: "bootstrap-expect and bootstrap",
  1559  			args: []string{
  1560  				`-datacenter=a`,
  1561  				`-data-dir=` + dataDir,
  1562  			},
  1563  			json: []string{`{ "bootstrap": true, "bootstrap_expect": 3, "server": true }`},
  1564  			hcl:  []string{`bootstrap = true bootstrap_expect = 3 server = true`},
  1565  			err:  "'bootstrap_expect > 0' and 'bootstrap = true' are mutually exclusive",
  1566  		},
  1567  		{
  1568  			desc: "bootstrap-expect=1 equals bootstrap",
  1569  			args: []string{
  1570  				`-data-dir=` + dataDir,
  1571  			},
  1572  			json: []string{`{ "bootstrap_expect": 1, "server": true }`},
  1573  			hcl:  []string{`bootstrap_expect = 1 server = true`},
  1574  			patch: func(rt *RuntimeConfig) {
  1575  				rt.Bootstrap = true
  1576  				rt.BootstrapExpect = 0
  1577  				rt.LeaveOnTerm = false
  1578  				rt.ServerMode = true
  1579  				rt.SkipLeaveOnInt = true
  1580  				rt.DataDir = dataDir
  1581  			},
  1582  			warns: []string{"BootstrapExpect is set to 1; this is the same as Bootstrap mode.", "bootstrap = true: do not enable unless necessary"},
  1583  		},
  1584  		{
  1585  			desc: "bootstrap-expect=2 warning",
  1586  			args: []string{
  1587  				`-data-dir=` + dataDir,
  1588  			},
  1589  			json: []string{`{ "bootstrap_expect": 2, "server": true }`},
  1590  			hcl:  []string{`bootstrap_expect = 2 server = true`},
  1591  			patch: func(rt *RuntimeConfig) {
  1592  				rt.BootstrapExpect = 2
  1593  				rt.LeaveOnTerm = false
  1594  				rt.ServerMode = true
  1595  				rt.SkipLeaveOnInt = true
  1596  				rt.DataDir = dataDir
  1597  			},
  1598  			warns: []string{
  1599  				`bootstrap_expect = 2: A cluster with 2 servers will provide no failure tolerance. See https://www.consul.io/docs/internals/consensus.html#deployment-table`,
  1600  				`bootstrap_expect > 0: expecting 2 servers`,
  1601  			},
  1602  		},
  1603  		{
  1604  			desc: "bootstrap-expect > 2 but even warning",
  1605  			args: []string{
  1606  				`-data-dir=` + dataDir,
  1607  			},
  1608  			json: []string{`{ "bootstrap_expect": 4, "server": true }`},
  1609  			hcl:  []string{`bootstrap_expect = 4 server = true`},
  1610  			patch: func(rt *RuntimeConfig) {
  1611  				rt.BootstrapExpect = 4
  1612  				rt.LeaveOnTerm = false
  1613  				rt.ServerMode = true
  1614  				rt.SkipLeaveOnInt = true
  1615  				rt.DataDir = dataDir
  1616  			},
  1617  			warns: []string{
  1618  				`bootstrap_expect is even number: A cluster with an even number of servers does not achieve optimum fault tolerance. See https://www.consul.io/docs/internals/consensus.html#deployment-table`,
  1619  				`bootstrap_expect > 0: expecting 4 servers`,
  1620  			},
  1621  		},
  1622  		{
  1623  			desc: "client mode sets LeaveOnTerm and SkipLeaveOnInt correctly",
  1624  			args: []string{
  1625  				`-data-dir=` + dataDir,
  1626  			},
  1627  			json: []string{`{ "server": false }`},
  1628  			hcl:  []string{` server = false`},
  1629  			patch: func(rt *RuntimeConfig) {
  1630  				rt.LeaveOnTerm = true
  1631  				rt.ServerMode = false
  1632  				rt.SkipLeaveOnInt = false
  1633  				rt.DataDir = dataDir
  1634  			},
  1635  		},
  1636  		{
  1637  			desc: "client does not allow socket",
  1638  			args: []string{
  1639  				`-datacenter=a`,
  1640  				`-data-dir=` + dataDir,
  1641  			},
  1642  			json: []string{`{ "client_addr": "unix:///foo" }`},
  1643  			hcl:  []string{`client_addr = "unix:///foo"`},
  1644  			err:  "client_addr cannot be a unix socket",
  1645  		},
  1646  		{
  1647  			desc: "datacenter invalid",
  1648  			args: []string{`-data-dir=` + dataDir},
  1649  			json: []string{`{ "datacenter": "%" }`},
  1650  			hcl:  []string{`datacenter = "%"`},
  1651  			err:  `datacenter cannot be "%". Please use only [a-z0-9-_]`,
  1652  		},
  1653  		{
  1654  			desc: "dns does not allow socket",
  1655  			args: []string{
  1656  				`-datacenter=a`,
  1657  				`-data-dir=` + dataDir,
  1658  			},
  1659  			json: []string{`{ "addresses": {"dns": "unix:///foo" } }`},
  1660  			hcl:  []string{`addresses = { dns = "unix:///foo" }`},
  1661  			err:  "DNS address cannot be a unix socket",
  1662  		},
  1663  		{
  1664  			desc: "ui and ui_dir",
  1665  			args: []string{
  1666  				`-datacenter=a`,
  1667  				`-data-dir=` + dataDir,
  1668  			},
  1669  			json: []string{`{ "ui": true, "ui_dir": "a" }`},
  1670  			hcl:  []string{`ui = true ui_dir = "a"`},
  1671  			err: "Both the ui and ui-dir flags were specified, please provide only one.\n" +
  1672  				"If trying to use your own web UI resources, use the ui-dir flag.\n" +
  1673  				"If using Consul version 0.7.0 or later, the web UI is included in the binary so use ui to enable it",
  1674  		},
  1675  
  1676  		// test ANY address failures
  1677  		// to avoid combinatory explosion for tests use 0.0.0.0, :: or [::] but not all of them
  1678  		{
  1679  			desc: "advertise_addr any",
  1680  			args: []string{
  1681  				`-data-dir=` + dataDir,
  1682  			},
  1683  			json: []string{`{ "advertise_addr": "0.0.0.0" }`},
  1684  			hcl:  []string{`advertise_addr = "0.0.0.0"`},
  1685  			err:  "Advertise address cannot be 0.0.0.0, :: or [::]",
  1686  		},
  1687  		{
  1688  			desc: "advertise_addr_wan any",
  1689  			args: []string{
  1690  				`-data-dir=` + dataDir,
  1691  			},
  1692  			json: []string{`{ "advertise_addr_wan": "::" }`},
  1693  			hcl:  []string{`advertise_addr_wan = "::"`},
  1694  			err:  "Advertise WAN address cannot be 0.0.0.0, :: or [::]",
  1695  		},
  1696  		{
  1697  			desc: "recursors any",
  1698  			args: []string{
  1699  				`-data-dir=` + dataDir,
  1700  			},
  1701  			json: []string{`{ "recursors": ["::"] }`},
  1702  			hcl:  []string{`recursors = ["::"]`},
  1703  			err:  "DNS recursor address cannot be 0.0.0.0, :: or [::]",
  1704  		},
  1705  		{
  1706  			desc: "dns_config.udp_answer_limit invalid",
  1707  			args: []string{
  1708  				`-data-dir=` + dataDir,
  1709  			},
  1710  			json: []string{`{ "dns_config": { "udp_answer_limit": -1 } }`},
  1711  			hcl:  []string{`dns_config = { udp_answer_limit = -1 }`},
  1712  			err:  "dns_config.udp_answer_limit cannot be -1. Must be greater than or equal to zero",
  1713  		},
  1714  		{
  1715  			desc: "dns_config.a_record_limit invalid",
  1716  			args: []string{
  1717  				`-data-dir=` + dataDir,
  1718  			},
  1719  			json: []string{`{ "dns_config": { "a_record_limit": -1 } }`},
  1720  			hcl:  []string{`dns_config = { a_record_limit = -1 }`},
  1721  			err:  "dns_config.a_record_limit cannot be -1. Must be greater than or equal to zero",
  1722  		},
  1723  		{
  1724  			desc: "performance.raft_multiplier < 0",
  1725  			args: []string{
  1726  				`-data-dir=` + dataDir,
  1727  			},
  1728  			json: []string{`{ "performance": { "raft_multiplier": -1 } }`},
  1729  			hcl:  []string{`performance = { raft_multiplier = -1 }`},
  1730  			err:  `performance.raft_multiplier cannot be -1. Must be between 1 and 10`,
  1731  		},
  1732  		{
  1733  			desc: "performance.raft_multiplier == 0",
  1734  			args: []string{
  1735  				`-data-dir=` + dataDir,
  1736  			},
  1737  			json: []string{`{ "performance": { "raft_multiplier": 0 } }`},
  1738  			hcl:  []string{`performance = { raft_multiplier = 0 }`},
  1739  			err:  `performance.raft_multiplier cannot be 0. Must be between 1 and 10`,
  1740  		},
  1741  		{
  1742  			desc: "performance.raft_multiplier > 10",
  1743  			args: []string{
  1744  				`-data-dir=` + dataDir,
  1745  			},
  1746  			json: []string{`{ "performance": { "raft_multiplier": 20 } }`},
  1747  			hcl:  []string{`performance = { raft_multiplier = 20 }`},
  1748  			err:  `performance.raft_multiplier cannot be 20. Must be between 1 and 10`,
  1749  		},
  1750  		{
  1751  			desc: "node_name invalid",
  1752  			args: []string{
  1753  				`-data-dir=` + dataDir,
  1754  				`-node=`,
  1755  			},
  1756  			hostname: func() (string, error) { return "", nil },
  1757  			err:      "node_name cannot be empty",
  1758  		},
  1759  		{
  1760  			desc: "node_meta key too long",
  1761  			args: []string{
  1762  				`-data-dir=` + dataDir,
  1763  			},
  1764  			json: []string{
  1765  				`{ "dns_config": { "udp_answer_limit": 1 } }`,
  1766  				`{ "node_meta": { "` + randomString(130) + `": "a" } }`,
  1767  			},
  1768  			hcl: []string{
  1769  				`dns_config = { udp_answer_limit = 1 }`,
  1770  				`node_meta = { "` + randomString(130) + `" = "a" }`,
  1771  			},
  1772  			err: "Key is too long (limit: 128 characters)",
  1773  		},
  1774  		{
  1775  			desc: "node_meta value too long",
  1776  			args: []string{
  1777  				`-data-dir=` + dataDir,
  1778  			},
  1779  			json: []string{
  1780  				`{ "dns_config": { "udp_answer_limit": 1 } }`,
  1781  				`{ "node_meta": { "a": "` + randomString(520) + `" } }`,
  1782  			},
  1783  			hcl: []string{
  1784  				`dns_config = { udp_answer_limit = 1 }`,
  1785  				`node_meta = { "a" = "` + randomString(520) + `" }`,
  1786  			},
  1787  			err: "Value is too long (limit: 512 characters)",
  1788  		},
  1789  		{
  1790  			desc: "node_meta too many keys",
  1791  			args: []string{
  1792  				`-data-dir=` + dataDir,
  1793  			},
  1794  			json: []string{
  1795  				`{ "dns_config": { "udp_answer_limit": 1 } }`,
  1796  				`{ "node_meta": {` + metaPairs(70, "json") + `} }`,
  1797  			},
  1798  			hcl: []string{
  1799  				`dns_config = { udp_answer_limit = 1 }`,
  1800  				`node_meta = {` + metaPairs(70, "hcl") + ` }`,
  1801  			},
  1802  			err: "Node metadata cannot contain more than 64 key/value pairs",
  1803  		},
  1804  		{
  1805  			desc: "unique listeners dns vs http",
  1806  			args: []string{
  1807  				`-data-dir=` + dataDir,
  1808  			},
  1809  			json: []string{`{
  1810  					"client_addr": "1.2.3.4",
  1811  					"ports": { "dns": 1000, "http": 1000 }
  1812  				}`},
  1813  			hcl: []string{`
  1814  					client_addr = "1.2.3.4"
  1815  					ports = { dns = 1000 http = 1000 }
  1816  				`},
  1817  			err: "HTTP address 1.2.3.4:1000 already configured for DNS",
  1818  		},
  1819  		{
  1820  			desc: "unique listeners dns vs https",
  1821  			args: []string{
  1822  				`-data-dir=` + dataDir,
  1823  			},
  1824  			json: []string{`{
  1825  					"client_addr": "1.2.3.4",
  1826  					"ports": { "dns": 1000, "https": 1000 }
  1827  				}`},
  1828  			hcl: []string{`
  1829  					client_addr = "1.2.3.4"
  1830  					ports = { dns = 1000 https = 1000 }
  1831  				`},
  1832  			err: "HTTPS address 1.2.3.4:1000 already configured for DNS",
  1833  		},
  1834  		{
  1835  			desc: "unique listeners http vs https",
  1836  			args: []string{
  1837  				`-data-dir=` + dataDir,
  1838  			},
  1839  			json: []string{`{
  1840  					"client_addr": "1.2.3.4",
  1841  					"ports": { "http": 1000, "https": 1000 }
  1842  				}`},
  1843  			hcl: []string{`
  1844  					client_addr = "1.2.3.4"
  1845  					ports = { http = 1000 https = 1000 }
  1846  				`},
  1847  			err: "HTTPS address 1.2.3.4:1000 already configured for HTTP",
  1848  		},
  1849  		{
  1850  			desc: "unique advertise addresses HTTP vs RPC",
  1851  			args: []string{
  1852  				`-data-dir=` + dataDir,
  1853  			},
  1854  			json: []string{`{
  1855  					"addresses": { "http": "10.0.0.1" },
  1856  					"ports": { "http": 1000, "server": 1000 }
  1857  				}`},
  1858  			hcl: []string{`
  1859  					addresses = { http = "10.0.0.1" }
  1860  					ports = { http = 1000 server = 1000 }
  1861  				`},
  1862  			err: "RPC Advertise address 10.0.0.1:1000 already configured for HTTP",
  1863  		},
  1864  		{
  1865  			desc: "unique advertise addresses RPC vs Serf LAN",
  1866  			args: []string{
  1867  				`-data-dir=` + dataDir,
  1868  			},
  1869  			json: []string{`{
  1870  					"ports": { "server": 1000, "serf_lan": 1000 }
  1871  				}`},
  1872  			hcl: []string{`
  1873  					ports = { server = 1000 serf_lan = 1000 }
  1874  				`},
  1875  			err: "Serf Advertise LAN address 10.0.0.1:1000 already configured for RPC Advertise",
  1876  		},
  1877  		{
  1878  			desc: "unique advertise addresses RPC vs Serf WAN",
  1879  			args: []string{
  1880  				`-data-dir=` + dataDir,
  1881  			},
  1882  			json: []string{`{
  1883  					"ports": { "server": 1000, "serf_wan": 1000 }
  1884  				}`},
  1885  			hcl: []string{`
  1886  					ports = { server = 1000 serf_wan = 1000 }
  1887  				`},
  1888  			err: "Serf Advertise WAN address 10.0.0.1:1000 already configured for RPC Advertise",
  1889  		},
  1890  		{
  1891  			desc: "sidecar_service can't have ID",
  1892  			args: []string{
  1893  				`-data-dir=` + dataDir,
  1894  			},
  1895  			json: []string{`{
  1896  				  "service": {
  1897  						"name": "web",
  1898  						"port": 1234,
  1899  						"connect": {
  1900  							"sidecar_service": {
  1901  								"ID": "random-sidecar-id"
  1902  							}
  1903  						}
  1904  					}
  1905  				}`},
  1906  			hcl: []string{`
  1907  				service {
  1908  					name = "web"
  1909  					port = 1234
  1910  					connect {
  1911  						sidecar_service {
  1912  							ID = "random-sidecar-id"
  1913  						}
  1914  					}
  1915  				}
  1916  			`},
  1917  			err: "sidecar_service can't specify an ID",
  1918  		},
  1919  		{
  1920  			desc: "sidecar_service can't have nested sidecar",
  1921  			args: []string{
  1922  				`-data-dir=` + dataDir,
  1923  			},
  1924  			json: []string{`{
  1925  				  "service": {
  1926  						"name": "web",
  1927  						"port": 1234,
  1928  						"connect": {
  1929  							"sidecar_service": {
  1930  								"connect": {
  1931  									"sidecar_service": {}
  1932  								}
  1933  							}
  1934  						}
  1935  					}
  1936  				}`},
  1937  			hcl: []string{`
  1938  				service {
  1939  					name = "web"
  1940  					port = 1234
  1941  					connect {
  1942  						sidecar_service {
  1943  							connect {
  1944  								sidecar_service {
  1945  								}
  1946  							}
  1947  						}
  1948  					}
  1949  				}
  1950  			`},
  1951  			err: "sidecar_service can't have a nested sidecar_service",
  1952  		},
  1953  		{
  1954  			desc: "sidecar_service can't have managed proxy",
  1955  			args: []string{
  1956  				`-data-dir=` + dataDir,
  1957  			},
  1958  			json: []string{`{
  1959  				  "service": {
  1960  						"name": "web",
  1961  						"port": 1234,
  1962  						"connect": {
  1963  							"sidecar_service": {
  1964  								"connect": {
  1965  									"proxy": {}
  1966  								}
  1967  							}
  1968  						}
  1969  					}
  1970  				}`},
  1971  			hcl: []string{`
  1972  				service {
  1973  					name = "web"
  1974  					port = 1234
  1975  					connect {
  1976  						sidecar_service {
  1977  							connect {
  1978  								proxy {
  1979  								}
  1980  							}
  1981  						}
  1982  					}
  1983  				}
  1984  			`},
  1985  			err: "sidecar_service can't have a managed proxy",
  1986  		},
  1987  		{
  1988  			desc: "telemetry.prefix_filter cannot be empty",
  1989  			args: []string{
  1990  				`-data-dir=` + dataDir,
  1991  			},
  1992  			json: []string{`{
  1993  					"telemetry": { "prefix_filter": [""] }
  1994  				}`},
  1995  			hcl: []string{`
  1996  					telemetry = { prefix_filter = [""] }
  1997  				`},
  1998  			patch: func(rt *RuntimeConfig) {
  1999  				rt.DataDir = dataDir
  2000  			},
  2001  			warns: []string{"Cannot have empty filter rule in prefix_filter"},
  2002  		},
  2003  		{
  2004  			desc: "telemetry.prefix_filter must start with + or -",
  2005  			args: []string{
  2006  				`-data-dir=` + dataDir,
  2007  			},
  2008  			json: []string{`{
  2009  					"telemetry": { "prefix_filter": ["+foo", "-bar", "nix"] }
  2010  				}`},
  2011  			hcl: []string{`
  2012  					telemetry = { prefix_filter = ["+foo", "-bar", "nix"] }
  2013  				`},
  2014  			patch: func(rt *RuntimeConfig) {
  2015  				rt.DataDir = dataDir
  2016  				rt.Telemetry.AllowedPrefixes = []string{"foo"}
  2017  				rt.Telemetry.BlockedPrefixes = []string{"bar"}
  2018  			},
  2019  			warns: []string{`Filter rule must begin with either '+' or '-': "nix"`},
  2020  		},
  2021  		{
  2022  			desc: "encrypt has invalid key",
  2023  			args: []string{
  2024  				`-data-dir=` + dataDir,
  2025  			},
  2026  			json: []string{`{ "encrypt": "this is not a valid key" }`},
  2027  			hcl:  []string{` encrypt = "this is not a valid key" `},
  2028  			err:  "encrypt has invalid key: illegal base64 data at input byte 4",
  2029  		},
  2030  		{
  2031  			desc: "encrypt given but LAN keyring exists",
  2032  			args: []string{
  2033  				`-data-dir=` + dataDir,
  2034  			},
  2035  			json: []string{`{ "encrypt": "i0P+gFTkLPg0h53eNYjydg==" }`},
  2036  			hcl:  []string{` encrypt = "i0P+gFTkLPg0h53eNYjydg==" `},
  2037  			patch: func(rt *RuntimeConfig) {
  2038  				rt.EncryptKey = "i0P+gFTkLPg0h53eNYjydg=="
  2039  				rt.DataDir = dataDir
  2040  			},
  2041  			pre: func() {
  2042  				writeFile(filepath.Join(dataDir, SerfLANKeyring), []byte("i0P+gFTkLPg0h53eNYjydg=="))
  2043  			},
  2044  			warns: []string{`WARNING: LAN keyring exists but -encrypt given, using keyring`},
  2045  		},
  2046  		{
  2047  			desc: "encrypt given but WAN keyring exists",
  2048  			args: []string{
  2049  				`-data-dir=` + dataDir,
  2050  			},
  2051  			json: []string{`{ "encrypt": "i0P+gFTkLPg0h53eNYjydg==", "server": true }`},
  2052  			hcl:  []string{` encrypt = "i0P+gFTkLPg0h53eNYjydg==" server = true `},
  2053  			patch: func(rt *RuntimeConfig) {
  2054  				rt.EncryptKey = "i0P+gFTkLPg0h53eNYjydg=="
  2055  				rt.ServerMode = true
  2056  				rt.LeaveOnTerm = false
  2057  				rt.SkipLeaveOnInt = true
  2058  				rt.DataDir = dataDir
  2059  			},
  2060  			pre: func() {
  2061  				writeFile(filepath.Join(dataDir, SerfWANKeyring), []byte("i0P+gFTkLPg0h53eNYjydg=="))
  2062  			},
  2063  			warns: []string{`WARNING: WAN keyring exists but -encrypt given, using keyring`},
  2064  		},
  2065  		{
  2066  			desc: "multiple check files",
  2067  			args: []string{
  2068  				`-data-dir=` + dataDir,
  2069  			},
  2070  			json: []string{
  2071  				`{ "check": { "name": "a", "args": ["/bin/true"] } }`,
  2072  				`{ "check": { "name": "b", "args": ["/bin/false"] } }`,
  2073  			},
  2074  			hcl: []string{
  2075  				`check = { name = "a" args = ["/bin/true"] }`,
  2076  				`check = { name = "b" args = ["/bin/false"] }`,
  2077  			},
  2078  			patch: func(rt *RuntimeConfig) {
  2079  				rt.Checks = []*structs.CheckDefinition{
  2080  					&structs.CheckDefinition{Name: "a", ScriptArgs: []string{"/bin/true"}},
  2081  					&structs.CheckDefinition{Name: "b", ScriptArgs: []string{"/bin/false"}},
  2082  				}
  2083  				rt.DataDir = dataDir
  2084  			},
  2085  		},
  2086  		{
  2087  			desc: "grpc check",
  2088  			args: []string{
  2089  				`-data-dir=` + dataDir,
  2090  			},
  2091  			json: []string{
  2092  				`{ "check": { "name": "a", "grpc": "localhost:12345/foo", "grpc_use_tls": true } }`,
  2093  			},
  2094  			hcl: []string{
  2095  				`check = { name = "a" grpc = "localhost:12345/foo", grpc_use_tls = true }`,
  2096  			},
  2097  			patch: func(rt *RuntimeConfig) {
  2098  				rt.Checks = []*structs.CheckDefinition{
  2099  					&structs.CheckDefinition{Name: "a", GRPC: "localhost:12345/foo", GRPCUseTLS: true},
  2100  				}
  2101  				rt.DataDir = dataDir
  2102  			},
  2103  		},
  2104  		{
  2105  			desc: "alias check with no node",
  2106  			args: []string{
  2107  				`-data-dir=` + dataDir,
  2108  			},
  2109  			json: []string{
  2110  				`{ "check": { "name": "a", "alias_service": "foo" } }`,
  2111  			},
  2112  			hcl: []string{
  2113  				`check = { name = "a", alias_service = "foo" }`,
  2114  			},
  2115  			patch: func(rt *RuntimeConfig) {
  2116  				rt.Checks = []*structs.CheckDefinition{
  2117  					&structs.CheckDefinition{Name: "a", AliasService: "foo"},
  2118  				}
  2119  				rt.DataDir = dataDir
  2120  			},
  2121  		},
  2122  		{
  2123  			desc: "multiple service files",
  2124  			args: []string{
  2125  				`-data-dir=` + dataDir,
  2126  			},
  2127  			json: []string{
  2128  				`{ "service": { "name": "a", "port": 80 } }`,
  2129  				`{ "service": { "name": "b", "port": 90, "meta": {"my": "value"}, "weights": {"passing": 13} } }`,
  2130  			},
  2131  			hcl: []string{
  2132  				`service = { name = "a" port = 80 }`,
  2133  				`service = { name = "b" port = 90 meta={my="value"}, weights={passing=13}}`,
  2134  			},
  2135  			patch: func(rt *RuntimeConfig) {
  2136  				rt.Services = []*structs.ServiceDefinition{
  2137  					&structs.ServiceDefinition{Name: "a", Port: 80, Weights: &structs.Weights{
  2138  						Passing: 1,
  2139  						Warning: 1,
  2140  					}},
  2141  					&structs.ServiceDefinition{Name: "b", Port: 90, Meta: map[string]string{"my": "value"}, Weights: &structs.Weights{
  2142  						Passing: 13,
  2143  						Warning: 1,
  2144  					}},
  2145  				}
  2146  				rt.DataDir = dataDir
  2147  			},
  2148  		},
  2149  		{
  2150  			desc: "service with wrong meta: too long key",
  2151  			args: []string{
  2152  				`-data-dir=` + dataDir,
  2153  			},
  2154  			json: []string{
  2155  				`{ "service": { "name": "a", "port": 80, "meta": { "` + randomString(520) + `": "metaValue" } } }`,
  2156  			},
  2157  			hcl: []string{
  2158  				`service = { name = "a" port = 80, meta={` + randomString(520) + `="metaValue"} }`,
  2159  			},
  2160  			err: `Key is too long`,
  2161  		},
  2162  		{
  2163  			desc: "service with wrong meta: too long value",
  2164  			args: []string{
  2165  				`-data-dir=` + dataDir,
  2166  			},
  2167  			json: []string{
  2168  				`{ "service": { "name": "a", "port": 80, "meta": { "a": "` + randomString(520) + `" } } }`,
  2169  			},
  2170  			hcl: []string{
  2171  				`service = { name = "a" port = 80, meta={a="` + randomString(520) + `"} }`,
  2172  			},
  2173  			err: `Value is too long`,
  2174  		},
  2175  		{
  2176  			desc: "service with wrong meta: too many meta",
  2177  			args: []string{
  2178  				`-data-dir=` + dataDir,
  2179  			},
  2180  			json: []string{
  2181  				`{ "service": { "name": "a", "port": 80, "meta": { ` + metaPairs(70, "json") + `} } }`,
  2182  			},
  2183  			hcl: []string{
  2184  				`service = { name = "a" port = 80 meta={` + metaPairs(70, "hcl") + `} }`,
  2185  			},
  2186  			err: `invalid meta for service a: Node metadata cannot contain more than 64 key`,
  2187  		},
  2188  		{
  2189  			desc: "translated keys",
  2190  			args: []string{
  2191  				`-data-dir=` + dataDir,
  2192  			},
  2193  			json: []string{
  2194  				`{
  2195  					"service": {
  2196  						"name": "a",
  2197  						"port": 80,
  2198  						"enable_tag_override": true,
  2199  						"check": {
  2200  							"id": "x",
  2201  							"name": "y",
  2202  							"DockerContainerID": "z",
  2203  							"DeregisterCriticalServiceAfter": "10s",
  2204  							"ScriptArgs": ["a", "b"]
  2205  						}
  2206  					}
  2207  				}`,
  2208  			},
  2209  			hcl: []string{
  2210  				`service = {
  2211  					name = "a"
  2212  					port = 80
  2213  					enable_tag_override = true
  2214  					check = {
  2215  						id = "x"
  2216  						name = "y"
  2217  						DockerContainerID = "z"
  2218  						DeregisterCriticalServiceAfter = "10s"
  2219  						ScriptArgs = ["a", "b"]
  2220  					}
  2221  				}`,
  2222  			},
  2223  			patch: func(rt *RuntimeConfig) {
  2224  				rt.Services = []*structs.ServiceDefinition{
  2225  					&structs.ServiceDefinition{
  2226  						Name:              "a",
  2227  						Port:              80,
  2228  						EnableTagOverride: true,
  2229  						Checks: []*structs.CheckType{
  2230  							&structs.CheckType{
  2231  								CheckID:                        types.CheckID("x"),
  2232  								Name:                           "y",
  2233  								DockerContainerID:              "z",
  2234  								DeregisterCriticalServiceAfter: 10 * time.Second,
  2235  								ScriptArgs:                     []string{"a", "b"},
  2236  							},
  2237  						},
  2238  						Weights: &structs.Weights{
  2239  							Passing: 1,
  2240  							Warning: 1,
  2241  						},
  2242  					},
  2243  				}
  2244  				rt.DataDir = dataDir
  2245  			},
  2246  		},
  2247  		{
  2248  			desc: "ignore snapshot_agent sub-object",
  2249  			args: []string{
  2250  				`-data-dir=` + dataDir,
  2251  			},
  2252  			json: []string{
  2253  				`{ "snapshot_agent": { "dont": "care" } }`,
  2254  			},
  2255  			hcl: []string{
  2256  				`snapshot_agent = { dont = "care" }`,
  2257  			},
  2258  			patch: func(rt *RuntimeConfig) {
  2259  				rt.DataDir = dataDir
  2260  			},
  2261  		},
  2262  
  2263  		{
  2264  			desc: "Service managed proxy 'upstreams'",
  2265  			args: []string{
  2266  				`-data-dir=` + dataDir,
  2267  			},
  2268  			json: []string{
  2269  				`{
  2270  						"service": {
  2271  							"name": "web",
  2272  							"port": 8080,
  2273  							"connect": {
  2274  								"proxy": {
  2275  									"upstreams": [{
  2276  										"destination_name": "db",
  2277  										"local_bind_port": 1234
  2278  									}]
  2279  								}
  2280  							}
  2281  						}
  2282  					}`,
  2283  			},
  2284  			hcl: []string{
  2285  				`service {
  2286  					name = "web"
  2287  					port = 8080
  2288  					connect {
  2289  						proxy {
  2290  							upstreams {
  2291  								destination_name = "db"
  2292  								local_bind_port = 1234
  2293  							}
  2294  						}
  2295  					}
  2296  				}`,
  2297  			},
  2298  			patch: func(rt *RuntimeConfig) {
  2299  				rt.DataDir = dataDir
  2300  				rt.Services = []*structs.ServiceDefinition{
  2301  					&structs.ServiceDefinition{
  2302  						Name: "web",
  2303  						Port: 8080,
  2304  						Connect: &structs.ServiceConnect{
  2305  							Proxy: &structs.ServiceDefinitionConnectProxy{
  2306  								Upstreams: structs.Upstreams{
  2307  									{
  2308  										DestinationName: "db",
  2309  										DestinationType: structs.UpstreamDestTypeService,
  2310  										LocalBindPort:   1234,
  2311  									},
  2312  								},
  2313  							},
  2314  						},
  2315  						Weights: &structs.Weights{
  2316  							Passing: 1,
  2317  							Warning: 1,
  2318  						},
  2319  					},
  2320  				}
  2321  			},
  2322  		},
  2323  
  2324  		{
  2325  			desc: "Multiple service managed proxy 'upstreams'",
  2326  			args: []string{
  2327  				`-data-dir=` + dataDir,
  2328  			},
  2329  			json: []string{
  2330  				`{
  2331  						"service": {
  2332  							"name": "web",
  2333  							"port": 8080,
  2334  							"connect": {
  2335  								"proxy": {
  2336  									"upstreams": [{
  2337  										"destination_name": "db",
  2338  										"local_bind_port": 1234
  2339  									}, {
  2340  										"destination_name": "cache",
  2341  										"local_bind_port": 2345
  2342  									}]
  2343  								}
  2344  							}
  2345  						}
  2346  					}`,
  2347  			},
  2348  			hcl: []string{
  2349  				`service {
  2350  					name = "web"
  2351  					port = 8080
  2352  					connect {
  2353  						proxy {
  2354  							upstreams = [
  2355  								{
  2356  									destination_name = "db"
  2357  									local_bind_port = 1234
  2358  								},
  2359  							  {
  2360  									destination_name = "cache"
  2361  									local_bind_port = 2345
  2362  								}
  2363  							]
  2364  						}
  2365  					}
  2366  				}`,
  2367  			},
  2368  			patch: func(rt *RuntimeConfig) {
  2369  				rt.DataDir = dataDir
  2370  				rt.Services = []*structs.ServiceDefinition{
  2371  					&structs.ServiceDefinition{
  2372  						Name: "web",
  2373  						Port: 8080,
  2374  						Connect: &structs.ServiceConnect{
  2375  							Proxy: &structs.ServiceDefinitionConnectProxy{
  2376  								Upstreams: structs.Upstreams{
  2377  									{
  2378  										DestinationName: "db",
  2379  										DestinationType: structs.UpstreamDestTypeService,
  2380  										LocalBindPort:   1234,
  2381  									},
  2382  									{
  2383  										DestinationName: "cache",
  2384  										DestinationType: structs.UpstreamDestTypeService,
  2385  										LocalBindPort:   2345,
  2386  									},
  2387  								},
  2388  							},
  2389  						},
  2390  						Weights: &structs.Weights{
  2391  							Passing: 1,
  2392  							Warning: 1,
  2393  						},
  2394  					},
  2395  				}
  2396  			},
  2397  		},
  2398  
  2399  		{
  2400  			desc: "enabling Connect allow_managed_root",
  2401  			args: []string{
  2402  				`-data-dir=` + dataDir,
  2403  			},
  2404  			json: []string{
  2405  				`{ "connect": { "proxy": { "allow_managed_root": true } } }`,
  2406  			},
  2407  			hcl: []string{
  2408  				`connect { proxy { allow_managed_root = true } }`,
  2409  			},
  2410  			patch: func(rt *RuntimeConfig) {
  2411  				rt.DataDir = dataDir
  2412  				rt.ConnectProxyAllowManagedRoot = true
  2413  			},
  2414  		},
  2415  
  2416  		{
  2417  			desc: "enabling Connect allow_managed_api_registration",
  2418  			args: []string{
  2419  				`-data-dir=` + dataDir,
  2420  			},
  2421  			json: []string{
  2422  				`{ "connect": { "proxy": { "allow_managed_api_registration": true } } }`,
  2423  			},
  2424  			hcl: []string{
  2425  				`connect { proxy { allow_managed_api_registration = true } }`,
  2426  			},
  2427  			patch: func(rt *RuntimeConfig) {
  2428  				rt.DataDir = dataDir
  2429  				rt.ConnectProxyAllowManagedAPIRegistration = true
  2430  			},
  2431  		},
  2432  
  2433  		{
  2434  			// This tests that we correct added the nested paths to arrays of objects
  2435  			// to the exceptions in patchSliceOfMaps in config.go (for single service)
  2436  			desc: "service.connectsidecar_service with checks and upstreams",
  2437  			args: []string{
  2438  				`-data-dir=` + dataDir,
  2439  			},
  2440  			json: []string{`{
  2441  				  "service": {
  2442  						"name": "web",
  2443  						"port": 1234,
  2444  						"connect": {
  2445  							"sidecar_service": {
  2446  								"port": 2345,
  2447  								"checks": [
  2448  									{
  2449  										"TCP": "127.0.0.1:2345",
  2450  										"Interval": "10s"
  2451  									}
  2452  								],
  2453  								"proxy": {
  2454  									"upstreams": [
  2455  										{
  2456  											"destination_name": "db",
  2457  											"local_bind_port": 7000
  2458  										}
  2459  									]
  2460  								}
  2461  							}
  2462  						}
  2463  					}
  2464  				}`},
  2465  			hcl: []string{`
  2466  				service {
  2467  					name = "web"
  2468  					port = 1234
  2469  					connect {
  2470  						sidecar_service {
  2471  							port = 2345
  2472  							checks = [
  2473  								{
  2474  									tcp = "127.0.0.1:2345"
  2475  									interval = "10s"
  2476  								}
  2477  							]
  2478  							proxy {
  2479  								upstreams = [
  2480  									{
  2481  										destination_name = "db"
  2482  										local_bind_port = 7000
  2483  									},
  2484  								]
  2485  							}
  2486  						}
  2487  					}
  2488  				}
  2489  			`},
  2490  			patch: func(rt *RuntimeConfig) {
  2491  				rt.DataDir = dataDir
  2492  				rt.Services = []*structs.ServiceDefinition{
  2493  					{
  2494  						Name: "web",
  2495  						Port: 1234,
  2496  						Connect: &structs.ServiceConnect{
  2497  							SidecarService: &structs.ServiceDefinition{
  2498  								Port: 2345,
  2499  								Checks: structs.CheckTypes{
  2500  									{
  2501  										TCP:      "127.0.0.1:2345",
  2502  										Interval: 10 * time.Second,
  2503  									},
  2504  								},
  2505  								Proxy: &structs.ConnectProxyConfig{
  2506  									Upstreams: structs.Upstreams{
  2507  										structs.Upstream{
  2508  											DestinationType: "service",
  2509  											DestinationName: "db",
  2510  											LocalBindPort:   7000,
  2511  										},
  2512  									},
  2513  								},
  2514  								Weights: &structs.Weights{
  2515  									Passing: 1,
  2516  									Warning: 1,
  2517  								},
  2518  							},
  2519  						},
  2520  						Weights: &structs.Weights{
  2521  							Passing: 1,
  2522  							Warning: 1,
  2523  						},
  2524  					},
  2525  				}
  2526  			},
  2527  		},
  2528  		{
  2529  			// This tests that we correct added the nested paths to arrays of objects
  2530  			// to the exceptions in patchSliceOfMaps in config.go (for service*s*)
  2531  			desc: "services.connect.sidecar_service with checks and upstreams",
  2532  			args: []string{
  2533  				`-data-dir=` + dataDir,
  2534  			},
  2535  			json: []string{`{
  2536  				  "services": [{
  2537  						"name": "web",
  2538  						"port": 1234,
  2539  						"connect": {
  2540  							"sidecar_service": {
  2541  								"port": 2345,
  2542  								"checks": [
  2543  									{
  2544  										"TCP": "127.0.0.1:2345",
  2545  										"Interval": "10s"
  2546  									}
  2547  								],
  2548  								"proxy": {
  2549  									"upstreams": [
  2550  										{
  2551  											"destination_name": "db",
  2552  											"local_bind_port": 7000
  2553  										}
  2554  									]
  2555  								}
  2556  							}
  2557  						}
  2558  					}]
  2559  				}`},
  2560  			hcl: []string{`
  2561  				services = [{
  2562  					name = "web"
  2563  					port = 1234
  2564  					connect {
  2565  						sidecar_service {
  2566  							port = 2345
  2567  							checks = [
  2568  								{
  2569  									tcp = "127.0.0.1:2345"
  2570  									interval = "10s"
  2571  								}
  2572  							]
  2573  							proxy {
  2574  								upstreams = [
  2575  									{
  2576  										destination_name = "db"
  2577  										local_bind_port = 7000
  2578  									},
  2579  								]
  2580  							}
  2581  						}
  2582  					}
  2583  				}]
  2584  			`},
  2585  			patch: func(rt *RuntimeConfig) {
  2586  				rt.DataDir = dataDir
  2587  				rt.Services = []*structs.ServiceDefinition{
  2588  					{
  2589  						Name: "web",
  2590  						Port: 1234,
  2591  						Connect: &structs.ServiceConnect{
  2592  							SidecarService: &structs.ServiceDefinition{
  2593  								Port: 2345,
  2594  								Checks: structs.CheckTypes{
  2595  									{
  2596  										TCP:      "127.0.0.1:2345",
  2597  										Interval: 10 * time.Second,
  2598  									},
  2599  								},
  2600  								Proxy: &structs.ConnectProxyConfig{
  2601  									Upstreams: structs.Upstreams{
  2602  										structs.Upstream{
  2603  											DestinationType: "service",
  2604  											DestinationName: "db",
  2605  											LocalBindPort:   7000,
  2606  										},
  2607  									},
  2608  								},
  2609  								Weights: &structs.Weights{
  2610  									Passing: 1,
  2611  									Warning: 1,
  2612  								},
  2613  							},
  2614  						},
  2615  						Weights: &structs.Weights{
  2616  							Passing: 1,
  2617  							Warning: 1,
  2618  						},
  2619  					},
  2620  				}
  2621  			},
  2622  		},
  2623  		{
  2624  			// This tests checks that VerifyServerHostname implies VerifyOutgoing
  2625  			desc: "verify_server_hostname implies verify_outgoing",
  2626  			args: []string{
  2627  				`-data-dir=` + dataDir,
  2628  			},
  2629  			json: []string{`{
  2630  			  "verify_server_hostname": true
  2631  			}`},
  2632  			hcl: []string{`
  2633  			  verify_server_hostname = true
  2634  			`},
  2635  			patch: func(rt *RuntimeConfig) {
  2636  				rt.DataDir = dataDir
  2637  				rt.VerifyServerHostname = true
  2638  				rt.VerifyOutgoing = true
  2639  			},
  2640  		},
  2641  		{
  2642  			desc: "test connect vault provider configuration",
  2643  			args: []string{
  2644  				`-data-dir=` + dataDir,
  2645  			},
  2646  			json: []string{`{
  2647  				"connect": {
  2648  					"enabled": true,
  2649  					"ca_provider": "vault",
  2650  					"ca_config": {
  2651  						"ca_file": "/capath/ca.pem",
  2652  						"ca_path": "/capath/",
  2653  						"cert_file": "/certpath/cert.pem",
  2654  						"key_file": "/certpath/key.pem",
  2655  						"tls_server_name": "server.name",
  2656  						"tls_skip_verify": true,
  2657  						"token": "abc",
  2658  						"root_pki_path": "consul-vault",
  2659  						"intermediate_pki_path": "connect-intermediate"
  2660  					}
  2661  				}
  2662  			}`},
  2663  			hcl: []string{`
  2664  			  connect {
  2665  					enabled = true
  2666  					ca_provider = "vault"
  2667  					ca_config {
  2668  						ca_file = "/capath/ca.pem"
  2669  						ca_path = "/capath/"
  2670  						cert_file = "/certpath/cert.pem"
  2671  						key_file = "/certpath/key.pem"
  2672  						tls_server_name = "server.name"
  2673  						tls_skip_verify = true
  2674  						token = "abc"
  2675  						root_pki_path = "consul-vault"
  2676  						intermediate_pki_path = "connect-intermediate"
  2677  					}
  2678  				}
  2679  			`},
  2680  			patch: func(rt *RuntimeConfig) {
  2681  				rt.DataDir = dataDir
  2682  				rt.ConnectEnabled = true
  2683  				rt.ConnectCAProvider = "vault"
  2684  				rt.ConnectCAConfig = map[string]interface{}{
  2685  					"CAFile":              "/capath/ca.pem",
  2686  					"CAPath":              "/capath/",
  2687  					"CertFile":            "/certpath/cert.pem",
  2688  					"KeyFile":             "/certpath/key.pem",
  2689  					"TLSServerName":       "server.name",
  2690  					"TLSSkipVerify":       true,
  2691  					"Token":               "abc",
  2692  					"RootPKIPath":         "consul-vault",
  2693  					"IntermediatePKIPath": "connect-intermediate",
  2694  				}
  2695  			},
  2696  		},
  2697  	}
  2698  
  2699  	testConfig(t, tests, dataDir)
  2700  }
  2701  
  2702  func testConfig(t *testing.T, tests []configTest, dataDir string) {
  2703  	for _, tt := range tests {
  2704  		for pass, format := range []string{"json", "hcl"} {
  2705  			// clean data dir before every test
  2706  			cleanDir(dataDir)
  2707  
  2708  			// when we test only flags then there are no JSON or HCL
  2709  			// sources and we need to make only one pass over the
  2710  			// tests.
  2711  			flagsOnly := len(tt.json) == 0 && len(tt.hcl) == 0
  2712  			if flagsOnly && pass > 0 {
  2713  				continue
  2714  			}
  2715  
  2716  			// json and hcl sources need to be in sync
  2717  			// to make sure we're generating the same config
  2718  			if len(tt.json) != len(tt.hcl) && !tt.skipformat {
  2719  				t.Fatal(tt.desc, ": JSON and HCL test case out of sync")
  2720  			}
  2721  
  2722  			// select the source
  2723  			srcs, tails := tt.json, tt.jsontail
  2724  			if format == "hcl" {
  2725  				srcs, tails = tt.hcl, tt.hcltail
  2726  			}
  2727  
  2728  			// If we're skipping a format and the current format is empty,
  2729  			// then skip it!
  2730  			if tt.skipformat && len(srcs) == 0 {
  2731  				continue
  2732  			}
  2733  
  2734  			// build the description
  2735  			var desc []string
  2736  			if !flagsOnly {
  2737  				desc = append(desc, format)
  2738  			}
  2739  			if tt.desc != "" {
  2740  				desc = append(desc, tt.desc)
  2741  			}
  2742  
  2743  			t.Run(strings.Join(desc, ":"), func(t *testing.T) {
  2744  				// first parse the flags
  2745  				flags := Flags{}
  2746  				fs := flag.NewFlagSet("", flag.ContinueOnError)
  2747  				AddFlags(fs, &flags)
  2748  				err := fs.Parse(tt.args)
  2749  				if err != nil {
  2750  					t.Fatalf("ParseFlags failed: %s", err)
  2751  				}
  2752  				flags.Args = fs.Args()
  2753  
  2754  				if tt.pre != nil {
  2755  					tt.pre()
  2756  				}
  2757  				defer func() {
  2758  					if tt.post != nil {
  2759  						tt.post()
  2760  					}
  2761  				}()
  2762  
  2763  				// Then create a builder with the flags.
  2764  				b, err := NewBuilder(flags)
  2765  				if err != nil {
  2766  					t.Fatal("NewBuilder", err)
  2767  				}
  2768  
  2769  				// mock the hostname function unless a mock is provided
  2770  				b.Hostname = tt.hostname
  2771  				if b.Hostname == nil {
  2772  					b.Hostname = func() (string, error) { return "nodex", nil }
  2773  				}
  2774  
  2775  				// mock the ip address detection
  2776  				privatev4 := tt.privatev4
  2777  				if privatev4 == nil {
  2778  					privatev4 = func() ([]*net.IPAddr, error) {
  2779  						return []*net.IPAddr{ipAddr("10.0.0.1")}, nil
  2780  					}
  2781  				}
  2782  				publicv6 := tt.publicv6
  2783  				if publicv6 == nil {
  2784  					publicv6 = func() ([]*net.IPAddr, error) {
  2785  						return []*net.IPAddr{ipAddr("dead:beef::1")}, nil
  2786  					}
  2787  				}
  2788  				b.GetPrivateIPv4 = privatev4
  2789  				b.GetPublicIPv6 = publicv6
  2790  
  2791  				// read the source fragements
  2792  				for i, data := range srcs {
  2793  					b.Sources = append(b.Sources, Source{
  2794  						Name:   fmt.Sprintf("src-%d.%s", i, format),
  2795  						Format: format,
  2796  						Data:   data,
  2797  					})
  2798  				}
  2799  				for i, data := range tails {
  2800  					b.Tail = append(b.Tail, Source{
  2801  						Name:   fmt.Sprintf("tail-%d.%s", i, format),
  2802  						Format: format,
  2803  						Data:   data,
  2804  					})
  2805  				}
  2806  
  2807  				// build/merge the config fragments
  2808  				rt, err := b.BuildAndValidate()
  2809  				if err == nil && tt.err != "" {
  2810  					t.Fatalf("got no error want %q", tt.err)
  2811  				}
  2812  				if err != nil && tt.err == "" {
  2813  					t.Fatalf("got error %s want nil", err)
  2814  				}
  2815  				if err == nil && tt.err != "" {
  2816  					t.Fatalf("got nil want error to contain %q", tt.err)
  2817  				}
  2818  				if err != nil && tt.err != "" && !strings.Contains(err.Error(), tt.err) {
  2819  					t.Fatalf("error %q does not contain %q", err.Error(), tt.err)
  2820  				}
  2821  
  2822  				// check the warnings
  2823  				if !verify.Values(t, "warnings", b.Warnings, tt.warns) {
  2824  					t.FailNow()
  2825  				}
  2826  
  2827  				// stop if we expected an error
  2828  				if tt.err != "" {
  2829  					return
  2830  				}
  2831  
  2832  				// build a default configuration, then patch the fields we expect to change
  2833  				// and compare it with the generated configuration. Since the expected
  2834  				// runtime config has been validated we do not need to validate it again.
  2835  				x, err := NewBuilder(Flags{})
  2836  				if err != nil {
  2837  					t.Fatal(err)
  2838  				}
  2839  				x.Hostname = b.Hostname
  2840  				x.GetPrivateIPv4 = func() ([]*net.IPAddr, error) { return []*net.IPAddr{ipAddr("10.0.0.1")}, nil }
  2841  				x.GetPublicIPv6 = func() ([]*net.IPAddr, error) { return []*net.IPAddr{ipAddr("dead:beef::1")}, nil }
  2842  				patchedRT, err := x.Build()
  2843  				if err != nil {
  2844  					t.Fatalf("build default failed: %s", err)
  2845  				}
  2846  				if tt.patch != nil {
  2847  					tt.patch(&patchedRT)
  2848  				}
  2849  				// if err := x.Validate(wantRT); err != nil {
  2850  				// 	t.Fatalf("validate default failed: %s", err)
  2851  				// }
  2852  				if got, want := rt, patchedRT; !verify.Values(t, "", got, want) {
  2853  					t.FailNow()
  2854  				}
  2855  			})
  2856  		}
  2857  	}
  2858  }
  2859  
  2860  // TestFullConfig tests the conversion from a fully populated JSON or
  2861  // HCL config file to a RuntimeConfig structure. All fields must be set
  2862  // to a unique non-zero value.
  2863  //
  2864  // To aid populating the fields the following bash functions can be used
  2865  // to generate random strings and ints:
  2866  //
  2867  //   random-int() { echo $RANDOM }
  2868  //   random-string() { base64 /dev/urandom | tr -d '/+' | fold -w ${1:-32} | head -n 1 }
  2869  //
  2870  // To generate a random string of length 8 run the following command in
  2871  // a terminal:
  2872  //
  2873  //   random-string 8
  2874  //
  2875  func TestFullConfig(t *testing.T) {
  2876  	dataDir := testutil.TempDir(t, "consul")
  2877  	defer os.RemoveAll(dataDir)
  2878  
  2879  	cidr := func(s string) *net.IPNet {
  2880  		_, n, _ := net.ParseCIDR(s)
  2881  		return n
  2882  	}
  2883  
  2884  	flagSrc := []string{`-dev`}
  2885  	src := map[string]string{
  2886  		"json": `{
  2887  			"acl_agent_master_token": "furuQD0b",
  2888  			"acl_agent_token": "cOshLOQ2",
  2889  			"acl_datacenter": "m3urck3z",
  2890  			"acl_default_policy": "ArK3WIfE",
  2891  			"acl_down_policy": "vZXMfMP0",
  2892  			"acl_enforce_version_8": true,
  2893  			"acl_enable_key_list_policy": true,
  2894  			"acl_master_token": "C1Q1oIwh",
  2895  			"acl_replication_token": "LMmgy5dO",
  2896  			"acl_token": "O1El0wan",
  2897  			"acl_ttl": "18060s",
  2898  			"acl" : {
  2899  				"enabled" : true,
  2900  				"down_policy" : "03eb2aee",
  2901  				"default_policy" : "72c2e7a0",
  2902  				"enable_key_list_policy": false,
  2903  				"enable_token_persistence": true,
  2904  				"policy_ttl": "1123s",
  2905  				"token_ttl": "3321s",
  2906  				"enable_token_replication" : true,
  2907  				"tokens" : {
  2908  					"master" : "8a19ac27",
  2909  					"agent_master" : "64fd0e08",
  2910  					"replication" : "5795983a",
  2911  					"agent" : "bed2377c",
  2912  					"default" : "418fdff1"
  2913  				}
  2914  			},
  2915  			"addresses": {
  2916  				"dns": "93.95.95.81",
  2917  				"http": "83.39.91.39",
  2918  				"https": "95.17.17.19",
  2919  				"grpc": "32.31.61.91"
  2920  			},
  2921  			"advertise_addr": "17.99.29.16",
  2922  			"advertise_addr_wan": "78.63.37.19",
  2923  			"autopilot": {
  2924  				"cleanup_dead_servers": true,
  2925  				"disable_upgrade_migration": true,
  2926  				"last_contact_threshold": "12705s",
  2927  				"max_trailing_logs": 17849,
  2928  				"redundancy_zone_tag": "3IsufDJf",
  2929  				"server_stabilization_time": "23057s",
  2930  				"upgrade_version_tag": "W9pDwFAL"
  2931  			},
  2932  			"bind_addr": "16.99.34.17",
  2933  			"bootstrap": true,
  2934  			"bootstrap_expect": 53,
  2935  			"ca_file": "erA7T0PM",
  2936  			"ca_path": "mQEN1Mfp",
  2937  			"cert_file": "7s4QAzDk",
  2938  			"check": {
  2939  				"id": "fZaCAXww",
  2940  				"name": "OOM2eo0f",
  2941  				"notes": "zXzXI9Gt",
  2942  				"service_id": "L8G0QNmR",
  2943  				"token": "oo4BCTgJ",
  2944  				"status": "qLykAl5u",
  2945  				"args": ["f3BemRjy", "e5zgpef7"],
  2946  				"http": "29B93haH",
  2947  				"header": {
  2948  					"hBq0zn1q": [ "2a9o9ZKP", "vKwA5lR6" ],
  2949  					"f3r6xFtM": [ "RyuIdDWv", "QbxEcIUM" ]
  2950  				},
  2951  				"method": "Dou0nGT5",
  2952  				"tcp": "JY6fTTcw",
  2953  				"interval": "18714s",
  2954  				"docker_container_id": "qF66POS9",
  2955  				"shell": "sOnDy228",
  2956  				"tls_skip_verify": true,
  2957  				"timeout": "5954s",
  2958  				"ttl": "30044s",
  2959  				"deregister_critical_service_after": "13209s"
  2960  			},
  2961  			"checks": [
  2962  				{
  2963  					"id": "uAjE6m9Z",
  2964  					"name": "QsZRGpYr",
  2965  					"notes": "VJ7Sk4BY",
  2966  					"service_id": "lSulPcyz",
  2967  					"token": "toO59sh8",
  2968  					"status": "9RlWsXMV",
  2969  					"args": ["4BAJttck", "4D2NPtTQ"],
  2970  					"http": "dohLcyQ2",
  2971  					"header": {
  2972  						"ZBfTin3L": [ "1sDbEqYG", "lJGASsWK" ],
  2973  						"Ui0nU99X": [ "LMccm3Qe", "k5H5RggQ" ]
  2974  					},
  2975  					"method": "aldrIQ4l",
  2976  					"tcp": "RJQND605",
  2977  					"interval": "22164s",
  2978  					"docker_container_id": "ipgdFtjd",
  2979  					"shell": "qAeOYy0M",
  2980  					"tls_skip_verify": true,
  2981  					"timeout": "1813s",
  2982  					"ttl": "21743s",
  2983  					"deregister_critical_service_after": "14232s"
  2984  				},
  2985  				{
  2986  					"id": "Cqq95BhP",
  2987  					"name": "3qXpkS0i",
  2988  					"notes": "sb5qLTex",
  2989  					"service_id": "CmUUcRna",
  2990  					"token": "a3nQzHuy",
  2991  					"status": "irj26nf3",
  2992  					"args": ["9s526ogY", "gSlOHj1w"],
  2993  					"http": "yzhgsQ7Y",
  2994  					"header": {
  2995  						"zcqwA8dO": [ "qb1zx0DL", "sXCxPFsD" ],
  2996  						"qxvdnSE9": [ "6wBPUYdF", "YYh8wtSZ" ]
  2997  					},
  2998  					"method": "gLrztrNw",
  2999  					"tcp": "4jG5casb",
  3000  					"interval": "28767s",
  3001  					"docker_container_id": "THW6u7rL",
  3002  					"shell": "C1Zt3Zwh",
  3003  					"tls_skip_verify": true,
  3004  					"timeout": "18506s",
  3005  					"ttl": "31006s",
  3006  					"deregister_critical_service_after": "2366s"
  3007  				}
  3008  			],
  3009  			"check_update_interval": "16507s",
  3010  			"client_addr": "93.83.18.19",
  3011  			"connect": {
  3012  				"ca_provider": "consul",
  3013  				"ca_config": {
  3014  					"rotation_period": "90h",
  3015  					"leaf_cert_ttl": "1h",
  3016  					"csr_max_per_second": 100,
  3017  					"csr_max_concurrent": 2
  3018  				},
  3019  				"enabled": true,
  3020  				"proxy_defaults": {
  3021  					"exec_mode": "script",
  3022  					"daemon_command": ["consul", "connect", "proxy"],
  3023  					"script_command": ["proxyctl.sh"],
  3024  					"config": {
  3025  						"foo": "bar",
  3026  						"connect_timeout_ms": 1000,
  3027  						"pedantic_mode": true
  3028  					}
  3029  				}
  3030  			},
  3031  			"gossip_lan" : {
  3032  				"gossip_nodes": 6,
  3033  				"gossip_interval" : "25252s",
  3034  				"retransmit_mult" : 1234,
  3035  				"suspicion_mult"  : 1235,
  3036  				"probe_interval"  : "101ms",
  3037  				"probe_timeout"   : "102ms"
  3038  			},
  3039  			"gossip_wan" : {
  3040  				"gossip_nodes" : 2,
  3041  				"gossip_interval" : "6966s",
  3042  				"retransmit_mult" : 16384,
  3043  				"suspicion_mult"  : 16385,
  3044  				"probe_interval" : "103ms",
  3045  				"probe_timeout"  : "104ms"
  3046  			},
  3047  			"data_dir": "` + dataDir + `",
  3048  			"datacenter": "rzo029wg",
  3049  			"disable_anonymous_signature": true,
  3050  			"disable_coordinates": true,
  3051  			"disable_host_node_id": true,
  3052  			"disable_http_unprintable_char_filter": true,
  3053  			"disable_keyring_file": true,
  3054  			"disable_remote_exec": true,
  3055  			"disable_update_check": true,
  3056  			"discard_check_output": true,
  3057  			"discovery_max_stale": "5s",
  3058  			"domain": "7W1xXSqd",
  3059  			"dns_config": {
  3060  				"allow_stale": true,
  3061  				"a_record_limit": 29907,
  3062  				"disable_compression": true,
  3063  				"enable_truncate": true,
  3064  				"max_stale": "29685s",
  3065  				"node_ttl": "7084s",
  3066  				"only_passing": true,
  3067  				"recursor_timeout": "4427s",
  3068  				"service_ttl": {
  3069  					"*": "32030s"
  3070  				},
  3071  				"udp_answer_limit": 29909,
  3072  				"use_cache": true,
  3073  				"cache_max_age": "5m"
  3074  			},
  3075  			"enable_acl_replication": true,
  3076  			"enable_agent_tls_for_checks": true,
  3077  			"enable_debug": true,
  3078  			"enable_script_checks": true,
  3079  			"enable_local_script_checks": true,
  3080  			"enable_syslog": true,
  3081  			"encrypt": "A4wELWqH",
  3082  			"encrypt_verify_incoming": true,
  3083  			"encrypt_verify_outgoing": true,
  3084  			"http_config": {
  3085  				"block_endpoints": [ "RBvAFcGD", "fWOWFznh" ],
  3086  				"allow_write_http_from": [ "127.0.0.1/8", "22.33.44.55/32", "0.0.0.0/0" ],
  3087  				"response_headers": {
  3088  					"M6TKa9NP": "xjuxjOzQ",
  3089  					"JRCrHZed": "rl0mTx81"
  3090  				}
  3091  			},
  3092  			"key_file": "IEkkwgIA",
  3093  			"leave_on_terminate": true,
  3094  			"limits": {
  3095  				"rpc_rate": 12029.43,
  3096  				"rpc_max_burst": 44848
  3097  			},
  3098  			"log_level": "k1zo9Spt",
  3099  			"node_id": "AsUIlw99",
  3100  			"node_meta": {
  3101  				"5mgGQMBk": "mJLtVMSG",
  3102  				"A7ynFMJB": "0Nx6RGab"
  3103  			},
  3104  			"node_name": "otlLxGaI",
  3105  			"non_voting_server": true,
  3106  			"performance": {
  3107  				"leave_drain_time": "8265s",
  3108  				"raft_multiplier": 5,
  3109  				"rpc_hold_timeout": "15707s",
  3110  				"watch_soft_limit": ` + fmt.Sprint(consul.DefaultSoftWatchLimit) + `
  3111  			},
  3112  			"pid_file": "43xN80Km",
  3113  			"ports": {
  3114  				"dns": 7001,
  3115  				"http": 7999,
  3116  				"https": 15127,
  3117  				"server": 3757,
  3118  				"grpc": 4881,
  3119  				"proxy_min_port": 2000,
  3120  				"proxy_max_port": 3000,
  3121  				"sidecar_min_port": 8888,
  3122  				"sidecar_max_port": 9999
  3123  			},
  3124  			"protocol": 30793,
  3125  			"primary_datacenter": "ejtmd43d",
  3126  			"raft_protocol": 19016,
  3127  			"raft_snapshot_threshold": 16384,
  3128  			"raft_snapshot_interval": "30s",
  3129  			"reconnect_timeout": "23739s",
  3130  			"reconnect_timeout_wan": "26694s",
  3131  			"recursors": [ "63.38.39.58", "92.49.18.18" ],
  3132  			"rejoin_after_leave": true,
  3133  			"retry_interval": "8067s",
  3134  			"retry_interval_wan": "28866s",
  3135  			"retry_join": [ "pbsSFY7U", "l0qLtWij" ],
  3136  			"retry_join_wan": [ "PFsR02Ye", "rJdQIhER" ],
  3137  			"retry_max": 913,
  3138  			"retry_max_wan": 23160,
  3139  			"segment": "BC2NhTDi",
  3140  			"segments": [
  3141  				{
  3142  					"name": "PExYMe2E",
  3143  					"bind": "36.73.36.19",
  3144  					"port": 38295,
  3145  					"rpc_listener": true,
  3146  					"advertise": "63.39.19.18"
  3147  				},
  3148  				{
  3149  					"name": "UzCvJgup",
  3150  					"bind": "37.58.38.19",
  3151  					"port": 39292,
  3152  					"rpc_listener": true,
  3153  					"advertise": "83.58.26.27"
  3154  				}
  3155  			],
  3156  			"serf_lan": "99.43.63.15",
  3157  			"serf_wan": "67.88.33.19",
  3158  			"server": true,
  3159  			"server_name": "Oerr9n1G",
  3160  			"service": {
  3161  				"id": "dLOXpSCI",
  3162  				"name": "o1ynPkp0",
  3163  				"meta": {
  3164  					"mymeta": "data"
  3165  				},
  3166  				"tags": ["nkwshvM5", "NTDWn3ek"],
  3167  				"address": "cOlSOhbp",
  3168  				"token": "msy7iWER",
  3169  				"port": 24237,
  3170  				"weights": {
  3171  					"passing": 100,
  3172  					"warning": 1
  3173  				},
  3174  				"enable_tag_override": true,
  3175  				"check": {
  3176  					"id": "RMi85Dv8",
  3177  					"name": "iehanzuq",
  3178  					"status": "rCvn53TH",
  3179  					"notes": "fti5lfF3",
  3180  					"args": ["16WRUmwS", "QWk7j7ae"],
  3181  					"http": "dl3Fgme3",
  3182  					"header": {
  3183  						"rjm4DEd3": ["2m3m2Fls"],
  3184  						"l4HwQ112": ["fk56MNlo", "dhLK56aZ"]
  3185  					},
  3186  					"method": "9afLm3Mj",
  3187  					"tcp": "fjiLFqVd",
  3188  					"interval": "23926s",
  3189  					"docker_container_id": "dO5TtRHk",
  3190  					"shell": "e6q2ttES",
  3191  					"tls_skip_verify": true,
  3192  					"timeout": "38483s",
  3193  					"ttl": "10943s",
  3194  					"deregister_critical_service_after": "68787s"
  3195  				},
  3196  				"checks": [
  3197  					{
  3198  						"id": "Zv99e9Ka",
  3199  						"name": "sgV4F7Pk",
  3200  						"notes": "yP5nKbW0",
  3201  						"status": "7oLMEyfu",
  3202  						"args": ["5wEZtZpv", "0Ihyk8cS"],
  3203  						"http": "KyDjGY9H",
  3204  						"header": {
  3205  							"gv5qefTz": [ "5Olo2pMG", "PvvKWQU5" ],
  3206  							"SHOVq1Vv": [ "jntFhyym", "GYJh32pp" ]
  3207  						},
  3208  						"method": "T66MFBfR",
  3209  						"tcp": "bNnNfx2A",
  3210  						"interval": "22224s",
  3211  						"docker_container_id": "ipgdFtjd",
  3212  						"shell": "omVZq7Sz",
  3213  						"tls_skip_verify": true,
  3214  						"timeout": "18913s",
  3215  						"ttl": "44743s",
  3216  						"deregister_critical_service_after": "8482s"
  3217  					},
  3218  					{
  3219  						"id": "G79O6Mpr",
  3220  						"name": "IEqrzrsd",
  3221  						"notes": "SVqApqeM",
  3222  						"status": "XXkVoZXt",
  3223  						"args": ["wD05Bvao", "rLYB7kQC"],
  3224  						"http": "kyICZsn8",
  3225  						"header": {
  3226  							"4ebP5vL4": [ "G20SrL5Q", "DwPKlMbo" ],
  3227  							"p2UI34Qz": [ "UsG1D0Qh", "NHhRiB6s" ]
  3228  						},
  3229  						"method": "ciYHWors",
  3230  						"tcp": "FfvCwlqH",
  3231  						"interval": "12356s",
  3232  						"docker_container_id": "HBndBU6R",
  3233  						"shell": "hVI33JjA",
  3234  						"tls_skip_verify": true,
  3235  						"timeout": "38282s",
  3236  						"ttl": "1181s",
  3237  						"deregister_critical_service_after": "4992s"
  3238  					}
  3239  				],
  3240  				"connect": {
  3241  					"native": true
  3242  				}
  3243  			},
  3244  			"services": [
  3245  				{
  3246  					"id": "wI1dzxS4",
  3247  					"name": "7IszXMQ1",
  3248  					"tags": ["0Zwg8l6v", "zebELdN5"],
  3249  					"address": "9RhqPSPB",
  3250  					"token": "myjKJkWH",
  3251  					"port": 72219,
  3252  					"enable_tag_override": true,
  3253  					"check": {
  3254  						"id": "qmfeO5if",
  3255  						"name": "atDGP7n5",
  3256  						"status": "pDQKEhWL",
  3257  						"notes": "Yt8EDLev",
  3258  						"args": ["81EDZLPa", "bPY5X8xd"],
  3259  						"http": "qzHYvmJO",
  3260  						"header": {
  3261  							"UkpmZ3a3": ["2dfzXuxZ"],
  3262  							"cVFpko4u": ["gGqdEB6k", "9LsRo22u"]
  3263  						},
  3264  						"method": "X5DrovFc",
  3265  						"tcp": "ICbxkpSF",
  3266  						"interval": "24392s",
  3267  						"docker_container_id": "ZKXr68Yb",
  3268  						"shell": "CEfzx0Fo",
  3269  						"tls_skip_verify": true,
  3270  						"timeout": "38333s",
  3271  						"ttl": "57201s",
  3272  						"deregister_critical_service_after": "44214s"
  3273  					},
  3274  					"connect": {
  3275  						"sidecar_service": {}
  3276  					}
  3277  				},
  3278  				{
  3279  					"id": "MRHVMZuD",
  3280  					"name": "6L6BVfgH",
  3281  					"tags": ["7Ale4y6o", "PMBW08hy"],
  3282  					"address": "R6H6g8h0",
  3283  					"token": "ZgY8gjMI",
  3284  					"port": 38292,
  3285  					"weights": {
  3286  						"passing": 1979,
  3287  						"warning": 6
  3288  					},
  3289  					"enable_tag_override": true,
  3290  					"checks": [
  3291  						{
  3292  							"id": "GTti9hCo",
  3293  							"name": "9OOS93ne",
  3294  							"notes": "CQy86DH0",
  3295  							"status": "P0SWDvrk",
  3296  							"args": ["EXvkYIuG", "BATOyt6h"],
  3297  							"http": "u97ByEiW",
  3298  							"header": {
  3299  								"MUlReo8L": [ "AUZG7wHG", "gsN0Dc2N" ],
  3300  								"1UJXjVrT": [ "OJgxzTfk", "xZZrFsq7" ]
  3301  							},
  3302  							"method": "5wkAxCUE",
  3303  							"tcp": "MN3oA9D2",
  3304  							"interval": "32718s",
  3305  							"docker_container_id": "cU15LMet",
  3306  							"shell": "nEz9qz2l",
  3307  							"tls_skip_verify": true,
  3308  							"timeout": "34738s",
  3309  							"ttl": "22773s",
  3310  							"deregister_critical_service_after": "84282s"
  3311  						},
  3312  						{
  3313  							"id": "UHsDeLxG",
  3314  							"name": "PQSaPWlT",
  3315  							"notes": "jKChDOdl",
  3316  							"status": "5qFz6OZn",
  3317  							"args": ["NMtYWlT9", "vj74JXsm"],
  3318  							"http": "1LBDJhw4",
  3319  							"header": {
  3320  								"cXPmnv1M": [ "imDqfaBx", "NFxZ1bQe" ],
  3321  								"vr7wY7CS": [ "EtCoNPPL", "9vAarJ5s" ]
  3322  							},
  3323  							"method": "wzByP903",
  3324  							"tcp": "2exjZIGE",
  3325  							"interval": "5656s",
  3326  							"docker_container_id": "5tDBWpfA",
  3327  							"shell": "rlTpLM8s",
  3328  							"tls_skip_verify": true,
  3329  							"timeout": "4868s",
  3330  							"ttl": "11222s",
  3331  							"deregister_critical_service_after": "68482s"
  3332  						}
  3333  					],
  3334  					"connect": {
  3335  						"proxy": {
  3336  							"exec_mode": "daemon",
  3337  							"command": ["awesome-proxy"],
  3338  							"config": {
  3339  								"foo": "qux"
  3340  							}
  3341  						}
  3342  					}
  3343  				},
  3344  				{
  3345  					"id": "Kh81CPF6",
  3346  					"kind": "connect-proxy",
  3347  					"name": "Kh81CPF6-proxy",
  3348  					"port": 31471,
  3349  					"proxy": {
  3350  						"config": {
  3351  								"cedGGtZf": "pWrUNiWw"
  3352  						},
  3353  						"destination_service_id": "6L6BVfgH-id",
  3354  						"destination_service_name": "6L6BVfgH",
  3355  						"local_service_address": "127.0.0.2",
  3356  						"local_service_port": 23759,
  3357  						"upstreams": [
  3358  							{
  3359  								"destination_name": "KPtAj2cb",
  3360  								"local_bind_port": 4051,
  3361  								"config": {
  3362  									"kzRnZOyd": "nUNKoL8H"
  3363  								}
  3364  							},
  3365  							{
  3366  								"destination_name": "KSd8HsRl",
  3367  								"destination_namespace": "9nakw0td",
  3368  								"destination_type": "prepared_query",
  3369  								"local_bind_address": "127.24.88.0",
  3370  								"local_bind_port": 11884
  3371  							}
  3372  						]
  3373  					}
  3374  				}
  3375  			],
  3376  			"session_ttl_min": "26627s",
  3377  			"skip_leave_on_interrupt": true,
  3378  			"start_join": [ "LR3hGDoG", "MwVpZ4Up" ],
  3379  			"start_join_wan": [ "EbFSc3nA", "kwXTh623" ],
  3380  			"syslog_facility": "hHv79Uia",
  3381  			"tagged_addresses": {
  3382  				"7MYgHrYH": "dALJAhLD",
  3383  				"h6DdBy6K": "ebrr9zZ8"
  3384  			},
  3385  			"telemetry": {
  3386  				"circonus_api_app": "p4QOTe9j",
  3387  				"circonus_api_token": "E3j35V23",
  3388  				"circonus_api_url": "mEMjHpGg",
  3389  				"circonus_broker_id": "BHlxUhed",
  3390  				"circonus_broker_select_tag": "13xy1gHm",
  3391  				"circonus_check_display_name": "DRSlQR6n",
  3392  				"circonus_check_force_metric_activation": "Ua5FGVYf",
  3393  				"circonus_check_id": "kGorutad",
  3394  				"circonus_check_instance_id": "rwoOL6R4",
  3395  				"circonus_check_search_tag": "ovT4hT4f",
  3396  				"circonus_check_tags": "prvO4uBl",
  3397  				"circonus_submission_interval": "DolzaflP",
  3398  				"circonus_submission_url": "gTcbS93G",
  3399  				"disable_hostname": true,
  3400  				"dogstatsd_addr": "0wSndumK",
  3401  				"dogstatsd_tags": [ "3N81zSUB","Xtj8AnXZ" ],
  3402  				"filter_default": true,
  3403  				"prefix_filter": [ "+oJotS8XJ","-cazlEhGn" ],
  3404  				"metrics_prefix": "ftO6DySn",
  3405  				"prometheus_retention_time": "15s",
  3406  				"statsd_address": "drce87cy",
  3407  				"statsite_address": "HpFwKB8R"
  3408  			},
  3409  			"tls_cipher_suites": "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
  3410  			"tls_min_version": "pAOWafkR",
  3411  			"tls_prefer_server_cipher_suites": true,
  3412  			"translate_wan_addrs": true,
  3413  			"ui": true,
  3414  			"ui_dir": "11IFzAUn",
  3415  			"unix_sockets": {
  3416  				"group": "8pFodrV8",
  3417  				"mode": "E8sAwOv4",
  3418  				"user": "E0nB1DwA"
  3419  			},
  3420  			"verify_incoming": true,
  3421  			"verify_incoming_https": true,
  3422  			"verify_incoming_rpc": true,
  3423  			"verify_outgoing": true,
  3424  			"verify_server_hostname": true,
  3425  			"watches": [
  3426  				{
  3427  					"type": "key",
  3428  					"datacenter": "GyE6jpeW",
  3429  					"key": "j9lF1Tve",
  3430  					"handler": "90N7S4LN"
  3431  				}, {
  3432  					"type": "keyprefix",
  3433  					"datacenter": "fYrl3F5d",
  3434  					"key": "sl3Dffu7",
  3435  					"args": ["dltjDJ2a", "flEa7C2d"]
  3436  				}
  3437  			]
  3438  		}`,
  3439  		"hcl": `
  3440  			acl_agent_master_token = "furuQD0b"
  3441  			acl_agent_token = "cOshLOQ2"
  3442  			acl_datacenter = "m3urck3z"
  3443  			acl_default_policy = "ArK3WIfE"
  3444  			acl_down_policy = "vZXMfMP0"
  3445  			acl_enforce_version_8 = true
  3446  			acl_enable_key_list_policy = true
  3447  			acl_master_token = "C1Q1oIwh"
  3448  			acl_replication_token = "LMmgy5dO"
  3449  			acl_token = "O1El0wan"
  3450  			acl_ttl = "18060s"
  3451  			acl = {
  3452  				enabled = true
  3453  				down_policy = "03eb2aee"
  3454  				default_policy = "72c2e7a0"
  3455  				enable_key_list_policy = false
  3456  				enable_token_persistence = true
  3457  				policy_ttl = "1123s"
  3458  				token_ttl = "3321s"
  3459  				enable_token_replication = true
  3460  				tokens = {
  3461  					master = "8a19ac27",
  3462  					agent_master = "64fd0e08",
  3463  					replication = "5795983a",
  3464  					agent = "bed2377c",
  3465  					default = "418fdff1"
  3466  				}
  3467  			}
  3468  			addresses = {
  3469  				dns = "93.95.95.81"
  3470  				http = "83.39.91.39"
  3471  				https = "95.17.17.19"
  3472  				grpc = "32.31.61.91"
  3473  			}
  3474  			advertise_addr = "17.99.29.16"
  3475  			advertise_addr_wan = "78.63.37.19"
  3476  			autopilot = {
  3477  				cleanup_dead_servers = true
  3478  				disable_upgrade_migration = true
  3479  				last_contact_threshold = "12705s"
  3480  				max_trailing_logs = 17849
  3481  				redundancy_zone_tag = "3IsufDJf"
  3482  				server_stabilization_time = "23057s"
  3483  				upgrade_version_tag = "W9pDwFAL"
  3484  			}
  3485  			bind_addr = "16.99.34.17"
  3486  			bootstrap = true
  3487  			bootstrap_expect = 53
  3488  			ca_file = "erA7T0PM"
  3489  			ca_path = "mQEN1Mfp"
  3490  			cert_file = "7s4QAzDk"
  3491  			check = {
  3492  				id = "fZaCAXww"
  3493  				name = "OOM2eo0f"
  3494  				notes = "zXzXI9Gt"
  3495  				service_id = "L8G0QNmR"
  3496  				token = "oo4BCTgJ"
  3497  				status = "qLykAl5u"
  3498  				args = ["f3BemRjy", "e5zgpef7"]
  3499  				http = "29B93haH"
  3500  				header = {
  3501  					hBq0zn1q = [ "2a9o9ZKP", "vKwA5lR6" ]
  3502  					f3r6xFtM = [ "RyuIdDWv", "QbxEcIUM" ]
  3503  				}
  3504  				method = "Dou0nGT5"
  3505  				tcp = "JY6fTTcw"
  3506  				interval = "18714s"
  3507  				docker_container_id = "qF66POS9"
  3508  				shell = "sOnDy228"
  3509  				tls_skip_verify = true
  3510  				timeout = "5954s"
  3511  				ttl = "30044s"
  3512  				deregister_critical_service_after = "13209s"
  3513  			},
  3514  			checks = [
  3515  				{
  3516  					id = "uAjE6m9Z"
  3517  					name = "QsZRGpYr"
  3518  					notes = "VJ7Sk4BY"
  3519  					service_id = "lSulPcyz"
  3520  					token = "toO59sh8"
  3521  					status = "9RlWsXMV"
  3522  					args = ["4BAJttck", "4D2NPtTQ"]
  3523  					http = "dohLcyQ2"
  3524  					header = {
  3525  						"ZBfTin3L" = [ "1sDbEqYG", "lJGASsWK" ]
  3526  						"Ui0nU99X" = [ "LMccm3Qe", "k5H5RggQ" ]
  3527  					}
  3528  					method = "aldrIQ4l"
  3529  					tcp = "RJQND605"
  3530  					interval = "22164s"
  3531  					docker_container_id = "ipgdFtjd"
  3532  					shell = "qAeOYy0M"
  3533  					tls_skip_verify = true
  3534  					timeout = "1813s"
  3535  					ttl = "21743s"
  3536  					deregister_critical_service_after = "14232s"
  3537  				},
  3538  				{
  3539  					id = "Cqq95BhP"
  3540  					name = "3qXpkS0i"
  3541  					notes = "sb5qLTex"
  3542  					service_id = "CmUUcRna"
  3543  					token = "a3nQzHuy"
  3544  					status = "irj26nf3"
  3545  					args = ["9s526ogY", "gSlOHj1w"]
  3546  					http = "yzhgsQ7Y"
  3547  					header = {
  3548  						"zcqwA8dO" = [ "qb1zx0DL", "sXCxPFsD" ]
  3549  						"qxvdnSE9" = [ "6wBPUYdF", "YYh8wtSZ" ]
  3550  					}
  3551  					method = "gLrztrNw"
  3552  					tcp = "4jG5casb"
  3553  					interval = "28767s"
  3554  					docker_container_id = "THW6u7rL"
  3555  					shell = "C1Zt3Zwh"
  3556  					tls_skip_verify = true
  3557  					timeout = "18506s"
  3558  					ttl = "31006s"
  3559  					deregister_critical_service_after = "2366s"
  3560  				}
  3561  			]
  3562  			check_update_interval = "16507s"
  3563  			client_addr = "93.83.18.19"
  3564  			connect {
  3565  				ca_provider = "consul"
  3566  				ca_config {
  3567  					rotation_period = "90h"
  3568  					leaf_cert_ttl = "1h"
  3569  					# hack float since json parses numbers as float and we have to
  3570  					# assert against the same thing
  3571  					csr_max_per_second = 100.0
  3572  					csr_max_concurrent = 2.0
  3573  				}
  3574  				enabled = true
  3575  				proxy_defaults {
  3576  					exec_mode = "script"
  3577  					daemon_command = ["consul", "connect", "proxy"]
  3578  					script_command = ["proxyctl.sh"]
  3579  					config = {
  3580  						foo = "bar"
  3581  						# hack float since json parses numbers as float and we have to
  3582  						# assert against the same thing
  3583  						connect_timeout_ms = 1000.0
  3584  						pedantic_mode = true
  3585  					}
  3586  				}
  3587  			}
  3588  			gossip_lan {
  3589  				gossip_nodes    = 6
  3590  				gossip_interval = "25252s"
  3591  				retransmit_mult = 1234
  3592  				suspicion_mult  = 1235
  3593  				probe_interval  = "101ms"
  3594  				probe_timeout   = "102ms"
  3595  			}
  3596  			gossip_wan {
  3597  				gossip_nodes    = 2
  3598  				gossip_interval = "6966s"
  3599  				retransmit_mult = 16384
  3600  				suspicion_mult  = 16385
  3601  				probe_interval  = "103ms"
  3602  				probe_timeout   = "104ms"
  3603  			}
  3604  			data_dir = "` + dataDir + `"
  3605  			datacenter = "rzo029wg"
  3606  			disable_anonymous_signature = true
  3607  			disable_coordinates = true
  3608  			disable_host_node_id = true
  3609  			disable_http_unprintable_char_filter = true
  3610  			disable_keyring_file = true
  3611  			disable_remote_exec = true
  3612  			disable_update_check = true
  3613  			discard_check_output = true
  3614  			discovery_max_stale = "5s"
  3615  			domain = "7W1xXSqd"
  3616  			dns_config {
  3617  				allow_stale = true
  3618  				a_record_limit = 29907
  3619  				disable_compression = true
  3620  				enable_truncate = true
  3621  				max_stale = "29685s"
  3622  				node_ttl = "7084s"
  3623  				only_passing = true
  3624  				recursor_timeout = "4427s"
  3625  				service_ttl = {
  3626  					"*" = "32030s"
  3627  				}
  3628  				udp_answer_limit = 29909
  3629  				use_cache = true
  3630  				cache_max_age = "5m"
  3631  			}
  3632  			enable_acl_replication = true
  3633  			enable_agent_tls_for_checks = true
  3634  			enable_debug = true
  3635  			enable_script_checks = true
  3636  			enable_local_script_checks = true
  3637  			enable_syslog = true
  3638  			encrypt = "A4wELWqH"
  3639  			encrypt_verify_incoming = true
  3640  			encrypt_verify_outgoing = true
  3641  			http_config {
  3642  				block_endpoints = [ "RBvAFcGD", "fWOWFznh" ]
  3643  				allow_write_http_from = [ "127.0.0.1/8", "22.33.44.55/32", "0.0.0.0/0" ]
  3644  				response_headers = {
  3645  					"M6TKa9NP" = "xjuxjOzQ"
  3646  					"JRCrHZed" = "rl0mTx81"
  3647  				}
  3648  			}
  3649  			key_file = "IEkkwgIA"
  3650  			leave_on_terminate = true
  3651  			limits {
  3652  				rpc_rate = 12029.43
  3653  				rpc_max_burst = 44848
  3654  			}
  3655  			log_level = "k1zo9Spt"
  3656  			node_id = "AsUIlw99"
  3657  			node_meta {
  3658  				"5mgGQMBk" = "mJLtVMSG"
  3659  				"A7ynFMJB" = "0Nx6RGab"
  3660  			}
  3661  			node_name = "otlLxGaI"
  3662  			non_voting_server = true
  3663  			performance {
  3664  				leave_drain_time = "8265s"
  3665  				raft_multiplier = 5
  3666  				rpc_hold_timeout = "15707s"
  3667  				watch_soft_limit = ` + fmt.Sprint(consul.DefaultSoftWatchLimit) + `
  3668  			}
  3669  			pid_file = "43xN80Km"
  3670  			ports {
  3671  				dns = 7001,
  3672  				http = 7999,
  3673  				https = 15127
  3674  				server = 3757
  3675  				grpc = 4881
  3676  				proxy_min_port = 2000
  3677  				proxy_max_port = 3000
  3678  				sidecar_min_port = 8888
  3679  				sidecar_max_port = 9999
  3680  			}
  3681  			protocol = 30793
  3682  			primary_datacenter = "ejtmd43d"
  3683  			raft_protocol = 19016
  3684  			raft_snapshot_threshold = 16384
  3685  			raft_snapshot_interval = "30s"
  3686  			reconnect_timeout = "23739s"
  3687  			reconnect_timeout_wan = "26694s"
  3688  			recursors = [ "63.38.39.58", "92.49.18.18" ]
  3689  			rejoin_after_leave = true
  3690  			retry_interval = "8067s"
  3691  			retry_interval_wan = "28866s"
  3692  			retry_join = [ "pbsSFY7U", "l0qLtWij" ]
  3693  			retry_join_wan = [ "PFsR02Ye", "rJdQIhER" ]
  3694  			retry_max = 913
  3695  			retry_max_wan = 23160
  3696  			segment = "BC2NhTDi"
  3697  			segments = [
  3698  				{
  3699  					name = "PExYMe2E"
  3700  					bind = "36.73.36.19"
  3701  					port = 38295
  3702  					rpc_listener = true
  3703  					advertise = "63.39.19.18"
  3704  				},
  3705  				{
  3706  					name = "UzCvJgup"
  3707  					bind = "37.58.38.19"
  3708  					port = 39292
  3709  					rpc_listener = true
  3710  					advertise = "83.58.26.27"
  3711  				}
  3712  			]
  3713  			serf_lan = "99.43.63.15"
  3714  			serf_wan = "67.88.33.19"
  3715  			server = true
  3716  			server_name = "Oerr9n1G"
  3717  			service = {
  3718  				id = "dLOXpSCI"
  3719  				name = "o1ynPkp0"
  3720  				meta = {
  3721  					mymeta = "data"
  3722  				}
  3723  				tags = ["nkwshvM5", "NTDWn3ek"]
  3724  				address = "cOlSOhbp"
  3725  				token = "msy7iWER"
  3726  				port = 24237
  3727  				weights = {
  3728  					passing = 100,
  3729  					warning = 1
  3730  				}
  3731  				enable_tag_override = true
  3732  				check = {
  3733  					id = "RMi85Dv8"
  3734  					name = "iehanzuq"
  3735  					status = "rCvn53TH"
  3736  					notes = "fti5lfF3"
  3737  					args = ["16WRUmwS", "QWk7j7ae"]
  3738  					http = "dl3Fgme3"
  3739  					header = {
  3740  						rjm4DEd3 = [ "2m3m2Fls" ]
  3741  						l4HwQ112 = [ "fk56MNlo", "dhLK56aZ" ]
  3742  					}
  3743  					method = "9afLm3Mj"
  3744  					tcp = "fjiLFqVd"
  3745  					interval = "23926s"
  3746  					docker_container_id = "dO5TtRHk"
  3747  					shell = "e6q2ttES"
  3748  					tls_skip_verify = true
  3749  					timeout = "38483s"
  3750  					ttl = "10943s"
  3751  					deregister_critical_service_after = "68787s"
  3752  				}
  3753  				checks = [
  3754  					{
  3755  						id = "Zv99e9Ka"
  3756  						name = "sgV4F7Pk"
  3757  						notes = "yP5nKbW0"
  3758  						status = "7oLMEyfu"
  3759  						args = ["5wEZtZpv", "0Ihyk8cS"]
  3760  						http = "KyDjGY9H"
  3761  						header = {
  3762  							"gv5qefTz" = [ "5Olo2pMG", "PvvKWQU5" ]
  3763  							"SHOVq1Vv" = [ "jntFhyym", "GYJh32pp" ]
  3764  						}
  3765  						method = "T66MFBfR"
  3766  						tcp = "bNnNfx2A"
  3767  						interval = "22224s"
  3768  						docker_container_id = "ipgdFtjd"
  3769  						shell = "omVZq7Sz"
  3770  						tls_skip_verify = true
  3771  						timeout = "18913s"
  3772  						ttl = "44743s"
  3773  						deregister_critical_service_after = "8482s"
  3774  					},
  3775  					{
  3776  						id = "G79O6Mpr"
  3777  						name = "IEqrzrsd"
  3778  						notes = "SVqApqeM"
  3779  						status = "XXkVoZXt"
  3780  						args = ["wD05Bvao", "rLYB7kQC"]
  3781  						http = "kyICZsn8"
  3782  						header = {
  3783  							"4ebP5vL4" = [ "G20SrL5Q", "DwPKlMbo" ]
  3784  							"p2UI34Qz" = [ "UsG1D0Qh", "NHhRiB6s" ]
  3785  						}
  3786  						method = "ciYHWors"
  3787  						tcp = "FfvCwlqH"
  3788  						interval = "12356s"
  3789  						docker_container_id = "HBndBU6R"
  3790  						shell = "hVI33JjA"
  3791  						tls_skip_verify = true
  3792  						timeout = "38282s"
  3793  						ttl = "1181s"
  3794  						deregister_critical_service_after = "4992s"
  3795  					}
  3796  				]
  3797  				connect {
  3798  					native = true
  3799  				}
  3800  			}
  3801  			services = [
  3802  				{
  3803  					id = "wI1dzxS4"
  3804  					name = "7IszXMQ1"
  3805  					tags = ["0Zwg8l6v", "zebELdN5"]
  3806  					address = "9RhqPSPB"
  3807  					token = "myjKJkWH"
  3808  					port = 72219
  3809  					enable_tag_override = true
  3810  					check = {
  3811  						id = "qmfeO5if"
  3812  						name = "atDGP7n5"
  3813  						status = "pDQKEhWL"
  3814  						notes = "Yt8EDLev"
  3815  						args = ["81EDZLPa", "bPY5X8xd"]
  3816  						http = "qzHYvmJO"
  3817  						header = {
  3818  							UkpmZ3a3 = [ "2dfzXuxZ" ]
  3819  							cVFpko4u = [ "gGqdEB6k", "9LsRo22u" ]
  3820  						}
  3821  						method = "X5DrovFc"
  3822  						tcp = "ICbxkpSF"
  3823  						interval = "24392s"
  3824  						docker_container_id = "ZKXr68Yb"
  3825  						shell = "CEfzx0Fo"
  3826  						tls_skip_verify = true
  3827  						timeout = "38333s"
  3828  						ttl = "57201s"
  3829  						deregister_critical_service_after = "44214s"
  3830  					}
  3831  					connect {
  3832  						sidecar_service {}
  3833  					}
  3834  				},
  3835  				{
  3836  					id = "MRHVMZuD"
  3837  					name = "6L6BVfgH"
  3838  					tags = ["7Ale4y6o", "PMBW08hy"]
  3839  					address = "R6H6g8h0"
  3840  					token = "ZgY8gjMI"
  3841  					port = 38292
  3842  					weights = {
  3843  						passing = 1979,
  3844  						warning = 6
  3845  					}
  3846  					enable_tag_override = true
  3847  					checks = [
  3848  						{
  3849  							id = "GTti9hCo"
  3850  							name = "9OOS93ne"
  3851  							notes = "CQy86DH0"
  3852  							status = "P0SWDvrk"
  3853  							args = ["EXvkYIuG", "BATOyt6h"]
  3854  							http = "u97ByEiW"
  3855  							header = {
  3856  								"MUlReo8L" = [ "AUZG7wHG", "gsN0Dc2N" ]
  3857  								"1UJXjVrT" = [ "OJgxzTfk", "xZZrFsq7" ]
  3858  							}
  3859  							method = "5wkAxCUE"
  3860  							tcp = "MN3oA9D2"
  3861  							interval = "32718s"
  3862  							docker_container_id = "cU15LMet"
  3863  							shell = "nEz9qz2l"
  3864  							tls_skip_verify = true
  3865  							timeout = "34738s"
  3866  							ttl = "22773s"
  3867  							deregister_critical_service_after = "84282s"
  3868  						},
  3869  						{
  3870  							id = "UHsDeLxG"
  3871  							name = "PQSaPWlT"
  3872  							notes = "jKChDOdl"
  3873  							status = "5qFz6OZn"
  3874  							args = ["NMtYWlT9", "vj74JXsm"]
  3875  							http = "1LBDJhw4"
  3876  							header = {
  3877  								"cXPmnv1M" = [ "imDqfaBx", "NFxZ1bQe" ],
  3878  								"vr7wY7CS" = [ "EtCoNPPL", "9vAarJ5s" ]
  3879  							}
  3880  							method = "wzByP903"
  3881  							tcp = "2exjZIGE"
  3882  							interval = "5656s"
  3883  							docker_container_id = "5tDBWpfA"
  3884  							shell = "rlTpLM8s"
  3885  							tls_skip_verify = true
  3886  							timeout = "4868s"
  3887  							ttl = "11222s"
  3888  							deregister_critical_service_after = "68482s"
  3889  						}
  3890  					]
  3891  					connect {
  3892  						proxy {
  3893  							exec_mode = "daemon"
  3894  							command = ["awesome-proxy"]
  3895  							config = {
  3896  								foo = "qux"
  3897  							}
  3898  						}
  3899  					}
  3900  				},
  3901  				{
  3902  					id = "Kh81CPF6"
  3903  					name = "Kh81CPF6-proxy"
  3904  					port = 31471
  3905  					kind = "connect-proxy"
  3906  					proxy {
  3907  						destination_service_name = "6L6BVfgH"
  3908  						destination_service_id = "6L6BVfgH-id"
  3909  						local_service_address = "127.0.0.2"
  3910  						local_service_port = 23759
  3911  						config {
  3912  							cedGGtZf = "pWrUNiWw"
  3913  						}
  3914  						upstreams = [
  3915  							{
  3916  								destination_name = "KPtAj2cb"
  3917  								local_bind_port = 4051
  3918  								config {
  3919  									kzRnZOyd = "nUNKoL8H"
  3920  								}
  3921  							},
  3922  							{
  3923  								destination_type = "prepared_query"
  3924  								destination_namespace = "9nakw0td"
  3925  								destination_name = "KSd8HsRl"
  3926  								local_bind_port = 11884
  3927  								local_bind_address = "127.24.88.0"
  3928  							},
  3929  						]
  3930  					}
  3931  				}
  3932  			]
  3933  			session_ttl_min = "26627s"
  3934  			skip_leave_on_interrupt = true
  3935  			start_join = [ "LR3hGDoG", "MwVpZ4Up" ]
  3936  			start_join_wan = [ "EbFSc3nA", "kwXTh623" ]
  3937  			syslog_facility = "hHv79Uia"
  3938  			tagged_addresses = {
  3939  				"7MYgHrYH" = "dALJAhLD"
  3940  				"h6DdBy6K" = "ebrr9zZ8"
  3941  			}
  3942  			telemetry {
  3943  				circonus_api_app = "p4QOTe9j"
  3944  				circonus_api_token = "E3j35V23"
  3945  				circonus_api_url = "mEMjHpGg"
  3946  				circonus_broker_id = "BHlxUhed"
  3947  				circonus_broker_select_tag = "13xy1gHm"
  3948  				circonus_check_display_name = "DRSlQR6n"
  3949  				circonus_check_force_metric_activation = "Ua5FGVYf"
  3950  				circonus_check_id = "kGorutad"
  3951  				circonus_check_instance_id = "rwoOL6R4"
  3952  				circonus_check_search_tag = "ovT4hT4f"
  3953  				circonus_check_tags = "prvO4uBl"
  3954  				circonus_submission_interval = "DolzaflP"
  3955  				circonus_submission_url = "gTcbS93G"
  3956  				disable_hostname = true
  3957  				dogstatsd_addr = "0wSndumK"
  3958  				dogstatsd_tags = [ "3N81zSUB","Xtj8AnXZ" ]
  3959  				filter_default = true
  3960  				prefix_filter = [ "+oJotS8XJ","-cazlEhGn" ]
  3961  				metrics_prefix = "ftO6DySn"
  3962  				prometheus_retention_time = "15s"
  3963  				statsd_address = "drce87cy"
  3964  				statsite_address = "HpFwKB8R"
  3965  			}
  3966  			tls_cipher_suites = "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
  3967  			tls_min_version = "pAOWafkR"
  3968  			tls_prefer_server_cipher_suites = true
  3969  			translate_wan_addrs = true
  3970  			ui = true
  3971  			ui_dir = "11IFzAUn"
  3972  			unix_sockets = {
  3973  				group = "8pFodrV8"
  3974  				mode = "E8sAwOv4"
  3975  				user = "E0nB1DwA"
  3976  			}
  3977  			verify_incoming = true
  3978  			verify_incoming_https = true
  3979  			verify_incoming_rpc = true
  3980  			verify_outgoing = true
  3981  			verify_server_hostname = true
  3982  			watches = [{
  3983  				type = "key"
  3984  				datacenter = "GyE6jpeW"
  3985  				key = "j9lF1Tve"
  3986  				handler = "90N7S4LN"
  3987  			}, {
  3988  				type = "keyprefix"
  3989  				datacenter = "fYrl3F5d"
  3990  				key = "sl3Dffu7"
  3991  				args = ["dltjDJ2a", "flEa7C2d"]
  3992  			}]
  3993  		`}
  3994  
  3995  	tail := map[string][]Source{
  3996  		"json": []Source{
  3997  			{
  3998  				Name:   "tail.non-user.json",
  3999  				Format: "json",
  4000  				Data: `
  4001  				{
  4002  					"acl_disabled_ttl": "957s",
  4003  					"acl" : {
  4004  						"disabled_ttl" : "957s"
  4005  					},
  4006  					"ae_interval": "10003s",
  4007  					"check_deregister_interval_min": "27870s",
  4008  					"check_reap_interval": "10662s",
  4009  					"discovery_max_stale": "5s",
  4010  					"segment_limit": 24705,
  4011  					"segment_name_limit": 27046,
  4012  					"sync_coordinate_interval_min": "27983s",
  4013  					"sync_coordinate_rate_target": 137.81
  4014  				}`,
  4015  			},
  4016  			{
  4017  				Name:   "tail.consul.json",
  4018  				Format: "json",
  4019  				Data: `
  4020  				{
  4021  					"consul": {
  4022  						"coordinate": {
  4023  							"update_batch_size": 9244,
  4024  							"update_max_batches": 15164,
  4025  							"update_period": "25093s"
  4026  						},
  4027  						"raft": {
  4028  							"election_timeout": "31947s",
  4029  							"heartbeat_timeout": "25699s",
  4030  							"leader_lease_timeout": "15351s"
  4031  						},
  4032  						"server": {
  4033  							"health_interval": "17455s"
  4034  						}
  4035  					}
  4036  				}`,
  4037  			},
  4038  		},
  4039  		"hcl": []Source{
  4040  			{
  4041  				Name:   "tail.non-user.hcl",
  4042  				Format: "hcl",
  4043  				Data: `
  4044  					acl_disabled_ttl = "957s"
  4045  					acl = {
  4046  						disabled_ttl = "957s"
  4047  					}
  4048  					ae_interval = "10003s"
  4049  					check_deregister_interval_min = "27870s"
  4050  					check_reap_interval = "10662s"
  4051  					discovery_max_stale = "5s"
  4052  					segment_limit = 24705
  4053  					segment_name_limit = 27046
  4054  					sync_coordinate_interval_min = "27983s"
  4055  					sync_coordinate_rate_target = 137.81
  4056  				`,
  4057  			},
  4058  			{
  4059  				Name:   "tail.consul.hcl",
  4060  				Format: "hcl",
  4061  				Data: `
  4062  					consul = {
  4063  						coordinate = {
  4064  							update_batch_size = 9244
  4065  							update_max_batches = 15164
  4066  							update_period = "25093s"
  4067  						}
  4068  						raft = {
  4069  							election_timeout = "31947s"
  4070  							heartbeat_timeout = "25699s"
  4071  							leader_lease_timeout = "15351s"
  4072  						}
  4073  						server = {
  4074  							health_interval = "17455s"
  4075  						}
  4076  					}
  4077  				`,
  4078  			},
  4079  		},
  4080  	}
  4081  
  4082  	want := RuntimeConfig{
  4083  		// non-user configurable values
  4084  		ACLDisabledTTL:             957 * time.Second,
  4085  		AEInterval:                 10003 * time.Second,
  4086  		CheckDeregisterIntervalMin: 27870 * time.Second,
  4087  		CheckReapInterval:          10662 * time.Second,
  4088  		SegmentLimit:               24705,
  4089  		SegmentNameLimit:           27046,
  4090  		SyncCoordinateIntervalMin:  27983 * time.Second,
  4091  		SyncCoordinateRateTarget:   137.81,
  4092  
  4093  		Revision:          "JNtPSav3",
  4094  		Version:           "R909Hblt",
  4095  		VersionPrerelease: "ZT1JOQLn",
  4096  
  4097  		// consul configuration
  4098  		ConsulCoordinateUpdateBatchSize:  9244,
  4099  		ConsulCoordinateUpdateMaxBatches: 15164,
  4100  		ConsulCoordinateUpdatePeriod:     25093 * time.Second,
  4101  		ConsulRaftElectionTimeout:        5 * 31947 * time.Second,
  4102  		ConsulRaftHeartbeatTimeout:       5 * 25699 * time.Second,
  4103  		ConsulRaftLeaderLeaseTimeout:     5 * 15351 * time.Second,
  4104  		GossipLANGossipInterval:          25252 * time.Second,
  4105  		GossipLANGossipNodes:             6,
  4106  		GossipLANProbeInterval:           101 * time.Millisecond,
  4107  		GossipLANProbeTimeout:            102 * time.Millisecond,
  4108  		GossipLANSuspicionMult:           1235,
  4109  		GossipLANRetransmitMult:          1234,
  4110  		GossipWANGossipInterval:          6966 * time.Second,
  4111  		GossipWANGossipNodes:             2,
  4112  		GossipWANProbeInterval:           103 * time.Millisecond,
  4113  		GossipWANProbeTimeout:            104 * time.Millisecond,
  4114  		GossipWANSuspicionMult:           16385,
  4115  		GossipWANRetransmitMult:          16384,
  4116  		ConsulServerHealthInterval:       17455 * time.Second,
  4117  
  4118  		// user configurable values
  4119  
  4120  		ACLAgentMasterToken:              "64fd0e08",
  4121  		ACLAgentToken:                    "bed2377c",
  4122  		ACLsEnabled:                      true,
  4123  		ACLDatacenter:                    "ejtmd43d",
  4124  		ACLDefaultPolicy:                 "72c2e7a0",
  4125  		ACLDownPolicy:                    "03eb2aee",
  4126  		ACLEnforceVersion8:               true,
  4127  		ACLEnableKeyListPolicy:           false,
  4128  		ACLEnableTokenPersistence:        true,
  4129  		ACLMasterToken:                   "8a19ac27",
  4130  		ACLReplicationToken:              "5795983a",
  4131  		ACLTokenTTL:                      3321 * time.Second,
  4132  		ACLPolicyTTL:                     1123 * time.Second,
  4133  		ACLToken:                         "418fdff1",
  4134  		ACLTokenReplication:              true,
  4135  		AdvertiseAddrLAN:                 ipAddr("17.99.29.16"),
  4136  		AdvertiseAddrWAN:                 ipAddr("78.63.37.19"),
  4137  		AutopilotCleanupDeadServers:      true,
  4138  		AutopilotDisableUpgradeMigration: true,
  4139  		AutopilotLastContactThreshold:    12705 * time.Second,
  4140  		AutopilotMaxTrailingLogs:         17849,
  4141  		AutopilotRedundancyZoneTag:       "3IsufDJf",
  4142  		AutopilotServerStabilizationTime: 23057 * time.Second,
  4143  		AutopilotUpgradeVersionTag:       "W9pDwFAL",
  4144  		BindAddr:                         ipAddr("16.99.34.17"),
  4145  		Bootstrap:                        true,
  4146  		BootstrapExpect:                  53,
  4147  		CAFile:                           "erA7T0PM",
  4148  		CAPath:                           "mQEN1Mfp",
  4149  		CertFile:                         "7s4QAzDk",
  4150  		Checks: []*structs.CheckDefinition{
  4151  			&structs.CheckDefinition{
  4152  				ID:         "uAjE6m9Z",
  4153  				Name:       "QsZRGpYr",
  4154  				Notes:      "VJ7Sk4BY",
  4155  				ServiceID:  "lSulPcyz",
  4156  				Token:      "toO59sh8",
  4157  				Status:     "9RlWsXMV",
  4158  				ScriptArgs: []string{"4BAJttck", "4D2NPtTQ"},
  4159  				HTTP:       "dohLcyQ2",
  4160  				Header: map[string][]string{
  4161  					"ZBfTin3L": []string{"1sDbEqYG", "lJGASsWK"},
  4162  					"Ui0nU99X": []string{"LMccm3Qe", "k5H5RggQ"},
  4163  				},
  4164  				Method:                         "aldrIQ4l",
  4165  				TCP:                            "RJQND605",
  4166  				Interval:                       22164 * time.Second,
  4167  				DockerContainerID:              "ipgdFtjd",
  4168  				Shell:                          "qAeOYy0M",
  4169  				TLSSkipVerify:                  true,
  4170  				Timeout:                        1813 * time.Second,
  4171  				TTL:                            21743 * time.Second,
  4172  				DeregisterCriticalServiceAfter: 14232 * time.Second,
  4173  			},
  4174  			&structs.CheckDefinition{
  4175  				ID:         "Cqq95BhP",
  4176  				Name:       "3qXpkS0i",
  4177  				Notes:      "sb5qLTex",
  4178  				ServiceID:  "CmUUcRna",
  4179  				Token:      "a3nQzHuy",
  4180  				Status:     "irj26nf3",
  4181  				ScriptArgs: []string{"9s526ogY", "gSlOHj1w"},
  4182  				HTTP:       "yzhgsQ7Y",
  4183  				Header: map[string][]string{
  4184  					"zcqwA8dO": []string{"qb1zx0DL", "sXCxPFsD"},
  4185  					"qxvdnSE9": []string{"6wBPUYdF", "YYh8wtSZ"},
  4186  				},
  4187  				Method:                         "gLrztrNw",
  4188  				TCP:                            "4jG5casb",
  4189  				Interval:                       28767 * time.Second,
  4190  				DockerContainerID:              "THW6u7rL",
  4191  				Shell:                          "C1Zt3Zwh",
  4192  				TLSSkipVerify:                  true,
  4193  				Timeout:                        18506 * time.Second,
  4194  				TTL:                            31006 * time.Second,
  4195  				DeregisterCriticalServiceAfter: 2366 * time.Second,
  4196  			},
  4197  			&structs.CheckDefinition{
  4198  				ID:         "fZaCAXww",
  4199  				Name:       "OOM2eo0f",
  4200  				Notes:      "zXzXI9Gt",
  4201  				ServiceID:  "L8G0QNmR",
  4202  				Token:      "oo4BCTgJ",
  4203  				Status:     "qLykAl5u",
  4204  				ScriptArgs: []string{"f3BemRjy", "e5zgpef7"},
  4205  				HTTP:       "29B93haH",
  4206  				Header: map[string][]string{
  4207  					"hBq0zn1q": {"2a9o9ZKP", "vKwA5lR6"},
  4208  					"f3r6xFtM": {"RyuIdDWv", "QbxEcIUM"},
  4209  				},
  4210  				Method:                         "Dou0nGT5",
  4211  				TCP:                            "JY6fTTcw",
  4212  				Interval:                       18714 * time.Second,
  4213  				DockerContainerID:              "qF66POS9",
  4214  				Shell:                          "sOnDy228",
  4215  				TLSSkipVerify:                  true,
  4216  				Timeout:                        5954 * time.Second,
  4217  				TTL:                            30044 * time.Second,
  4218  				DeregisterCriticalServiceAfter: 13209 * time.Second,
  4219  			},
  4220  		},
  4221  		CheckUpdateInterval:     16507 * time.Second,
  4222  		ClientAddrs:             []*net.IPAddr{ipAddr("93.83.18.19")},
  4223  		ConnectEnabled:          true,
  4224  		ConnectProxyBindMinPort: 2000,
  4225  		ConnectProxyBindMaxPort: 3000,
  4226  		ConnectSidecarMinPort:   8888,
  4227  		ConnectSidecarMaxPort:   9999,
  4228  		ConnectCAProvider:       "consul",
  4229  		ConnectCAConfig: map[string]interface{}{
  4230  			"RotationPeriod":   "90h",
  4231  			"LeafCertTTL":      "1h",
  4232  			"CSRMaxPerSecond":  float64(100),
  4233  			"CSRMaxConcurrent": float64(2),
  4234  		},
  4235  		ConnectProxyAllowManagedRoot:            false,
  4236  		ConnectProxyAllowManagedAPIRegistration: false,
  4237  		ConnectProxyDefaultExecMode:             "script",
  4238  		ConnectProxyDefaultDaemonCommand:        []string{"consul", "connect", "proxy"},
  4239  		ConnectProxyDefaultScriptCommand:        []string{"proxyctl.sh"},
  4240  		ConnectProxyDefaultConfig: map[string]interface{}{
  4241  			"foo":                "bar",
  4242  			"connect_timeout_ms": float64(1000),
  4243  			"pedantic_mode":      true,
  4244  		},
  4245  		DNSAddrs:                         []net.Addr{tcpAddr("93.95.95.81:7001"), udpAddr("93.95.95.81:7001")},
  4246  		DNSARecordLimit:                  29907,
  4247  		DNSAllowStale:                    true,
  4248  		DNSDisableCompression:            true,
  4249  		DNSDomain:                        "7W1xXSqd",
  4250  		DNSEnableTruncate:                true,
  4251  		DNSMaxStale:                      29685 * time.Second,
  4252  		DNSNodeTTL:                       7084 * time.Second,
  4253  		DNSOnlyPassing:                   true,
  4254  		DNSPort:                          7001,
  4255  		DNSRecursorTimeout:               4427 * time.Second,
  4256  		DNSRecursors:                     []string{"63.38.39.58", "92.49.18.18"},
  4257  		DNSSOA:                           RuntimeSOAConfig{Refresh: 3600, Retry: 600, Expire: 86400, Minttl: 0},
  4258  		DNSServiceTTL:                    map[string]time.Duration{"*": 32030 * time.Second},
  4259  		DNSUDPAnswerLimit:                29909,
  4260  		DNSNodeMetaTXT:                   true,
  4261  		DNSUseCache:                      true,
  4262  		DNSCacheMaxAge:                   5 * time.Minute,
  4263  		DataDir:                          dataDir,
  4264  		Datacenter:                       "rzo029wg",
  4265  		DevMode:                          true,
  4266  		DisableAnonymousSignature:        true,
  4267  		DisableCoordinates:               true,
  4268  		DisableHostNodeID:                true,
  4269  		DisableHTTPUnprintableCharFilter: true,
  4270  		DisableKeyringFile:               true,
  4271  		DisableRemoteExec:                true,
  4272  		DisableUpdateCheck:               true,
  4273  		DiscardCheckOutput:               true,
  4274  		DiscoveryMaxStale:                5 * time.Second,
  4275  		EnableAgentTLSForChecks:          true,
  4276  		EnableDebug:                      true,
  4277  		EnableRemoteScriptChecks:         true,
  4278  		EnableLocalScriptChecks:          true,
  4279  		EnableSyslog:                     true,
  4280  		EnableUI:                         true,
  4281  		EncryptKey:                       "A4wELWqH",
  4282  		EncryptVerifyIncoming:            true,
  4283  		EncryptVerifyOutgoing:            true,
  4284  		GRPCPort:                         4881,
  4285  		GRPCAddrs:                        []net.Addr{tcpAddr("32.31.61.91:4881")},
  4286  		HTTPAddrs:                        []net.Addr{tcpAddr("83.39.91.39:7999")},
  4287  		HTTPBlockEndpoints:               []string{"RBvAFcGD", "fWOWFznh"},
  4288  		AllowWriteHTTPFrom:               []*net.IPNet{cidr("127.0.0.0/8"), cidr("22.33.44.55/32"), cidr("0.0.0.0/0")},
  4289  		HTTPPort:                         7999,
  4290  		HTTPResponseHeaders:              map[string]string{"M6TKa9NP": "xjuxjOzQ", "JRCrHZed": "rl0mTx81"},
  4291  		HTTPSAddrs:                       []net.Addr{tcpAddr("95.17.17.19:15127")},
  4292  		HTTPSPort:                        15127,
  4293  		KeyFile:                          "IEkkwgIA",
  4294  		LeaveDrainTime:                   8265 * time.Second,
  4295  		LeaveOnTerm:                      true,
  4296  		LogLevel:                         "k1zo9Spt",
  4297  		NodeID:                           types.NodeID("AsUIlw99"),
  4298  		NodeMeta:                         map[string]string{"5mgGQMBk": "mJLtVMSG", "A7ynFMJB": "0Nx6RGab"},
  4299  		NodeName:                         "otlLxGaI",
  4300  		NonVotingServer:                  true,
  4301  		PidFile:                          "43xN80Km",
  4302  		PrimaryDatacenter:                "ejtmd43d",
  4303  		RPCAdvertiseAddr:                 tcpAddr("17.99.29.16:3757"),
  4304  		RPCBindAddr:                      tcpAddr("16.99.34.17:3757"),
  4305  		RPCHoldTimeout:                   15707 * time.Second,
  4306  		RPCProtocol:                      30793,
  4307  		RPCRateLimit:                     12029.43,
  4308  		RPCMaxBurst:                      44848,
  4309  		RaftProtocol:                     19016,
  4310  		RaftSnapshotThreshold:            16384,
  4311  		RaftSnapshotInterval:             30 * time.Second,
  4312  		ReconnectTimeoutLAN:              23739 * time.Second,
  4313  		ReconnectTimeoutWAN:              26694 * time.Second,
  4314  		RejoinAfterLeave:                 true,
  4315  		RetryJoinIntervalLAN:             8067 * time.Second,
  4316  		RetryJoinIntervalWAN:             28866 * time.Second,
  4317  		RetryJoinLAN:                     []string{"pbsSFY7U", "l0qLtWij"},
  4318  		RetryJoinMaxAttemptsLAN:          913,
  4319  		RetryJoinMaxAttemptsWAN:          23160,
  4320  		RetryJoinWAN:                     []string{"PFsR02Ye", "rJdQIhER"},
  4321  		SegmentName:                      "BC2NhTDi",
  4322  		Segments: []structs.NetworkSegment{
  4323  			{
  4324  				Name:        "PExYMe2E",
  4325  				Bind:        tcpAddr("36.73.36.19:38295"),
  4326  				Advertise:   tcpAddr("63.39.19.18:38295"),
  4327  				RPCListener: true,
  4328  			},
  4329  			{
  4330  				Name:        "UzCvJgup",
  4331  				Bind:        tcpAddr("37.58.38.19:39292"),
  4332  				Advertise:   tcpAddr("83.58.26.27:39292"),
  4333  				RPCListener: true,
  4334  			},
  4335  		},
  4336  		SerfPortLAN: 8301,
  4337  		SerfPortWAN: 8302,
  4338  		ServerMode:  true,
  4339  		ServerName:  "Oerr9n1G",
  4340  		ServerPort:  3757,
  4341  		Services: []*structs.ServiceDefinition{
  4342  			{
  4343  				ID:      "wI1dzxS4",
  4344  				Name:    "7IszXMQ1",
  4345  				Tags:    []string{"0Zwg8l6v", "zebELdN5"},
  4346  				Address: "9RhqPSPB",
  4347  				Token:   "myjKJkWH",
  4348  				Port:    72219,
  4349  				Weights: &structs.Weights{
  4350  					Passing: 1,
  4351  					Warning: 1,
  4352  				},
  4353  				EnableTagOverride: true,
  4354  				Checks: []*structs.CheckType{
  4355  					&structs.CheckType{
  4356  						CheckID:    "qmfeO5if",
  4357  						Name:       "atDGP7n5",
  4358  						Status:     "pDQKEhWL",
  4359  						Notes:      "Yt8EDLev",
  4360  						ScriptArgs: []string{"81EDZLPa", "bPY5X8xd"},
  4361  						HTTP:       "qzHYvmJO",
  4362  						Header: map[string][]string{
  4363  							"UkpmZ3a3": {"2dfzXuxZ"},
  4364  							"cVFpko4u": {"gGqdEB6k", "9LsRo22u"},
  4365  						},
  4366  						Method:                         "X5DrovFc",
  4367  						TCP:                            "ICbxkpSF",
  4368  						Interval:                       24392 * time.Second,
  4369  						DockerContainerID:              "ZKXr68Yb",
  4370  						Shell:                          "CEfzx0Fo",
  4371  						TLSSkipVerify:                  true,
  4372  						Timeout:                        38333 * time.Second,
  4373  						TTL:                            57201 * time.Second,
  4374  						DeregisterCriticalServiceAfter: 44214 * time.Second,
  4375  					},
  4376  				},
  4377  				// Note that although this SidecarService is only syntax sugar for
  4378  				// registering another service, that has to happen in the agent code so
  4379  				// it can make intelligent decisions about automatic port assignments
  4380  				// etc. So we expect config just to pass it through verbatim.
  4381  				Connect: &structs.ServiceConnect{
  4382  					SidecarService: &structs.ServiceDefinition{
  4383  						Weights: &structs.Weights{
  4384  							Passing: 1,
  4385  							Warning: 1,
  4386  						},
  4387  					},
  4388  				},
  4389  			},
  4390  			{
  4391  				ID:      "MRHVMZuD",
  4392  				Name:    "6L6BVfgH",
  4393  				Tags:    []string{"7Ale4y6o", "PMBW08hy"},
  4394  				Address: "R6H6g8h0",
  4395  				Token:   "ZgY8gjMI",
  4396  				Port:    38292,
  4397  				Weights: &structs.Weights{
  4398  					Passing: 1979,
  4399  					Warning: 6,
  4400  				},
  4401  				EnableTagOverride: true,
  4402  				Checks: structs.CheckTypes{
  4403  					&structs.CheckType{
  4404  						CheckID:    "GTti9hCo",
  4405  						Name:       "9OOS93ne",
  4406  						Notes:      "CQy86DH0",
  4407  						Status:     "P0SWDvrk",
  4408  						ScriptArgs: []string{"EXvkYIuG", "BATOyt6h"},
  4409  						HTTP:       "u97ByEiW",
  4410  						Header: map[string][]string{
  4411  							"MUlReo8L": {"AUZG7wHG", "gsN0Dc2N"},
  4412  							"1UJXjVrT": {"OJgxzTfk", "xZZrFsq7"},
  4413  						},
  4414  						Method:                         "5wkAxCUE",
  4415  						TCP:                            "MN3oA9D2",
  4416  						Interval:                       32718 * time.Second,
  4417  						DockerContainerID:              "cU15LMet",
  4418  						Shell:                          "nEz9qz2l",
  4419  						TLSSkipVerify:                  true,
  4420  						Timeout:                        34738 * time.Second,
  4421  						TTL:                            22773 * time.Second,
  4422  						DeregisterCriticalServiceAfter: 84282 * time.Second,
  4423  					},
  4424  					&structs.CheckType{
  4425  						CheckID:    "UHsDeLxG",
  4426  						Name:       "PQSaPWlT",
  4427  						Notes:      "jKChDOdl",
  4428  						Status:     "5qFz6OZn",
  4429  						ScriptArgs: []string{"NMtYWlT9", "vj74JXsm"},
  4430  						HTTP:       "1LBDJhw4",
  4431  						Header: map[string][]string{
  4432  							"cXPmnv1M": {"imDqfaBx", "NFxZ1bQe"},
  4433  							"vr7wY7CS": {"EtCoNPPL", "9vAarJ5s"},
  4434  						},
  4435  						Method:                         "wzByP903",
  4436  						TCP:                            "2exjZIGE",
  4437  						Interval:                       5656 * time.Second,
  4438  						DockerContainerID:              "5tDBWpfA",
  4439  						Shell:                          "rlTpLM8s",
  4440  						TLSSkipVerify:                  true,
  4441  						Timeout:                        4868 * time.Second,
  4442  						TTL:                            11222 * time.Second,
  4443  						DeregisterCriticalServiceAfter: 68482 * time.Second,
  4444  					},
  4445  				},
  4446  				Connect: &structs.ServiceConnect{
  4447  					Proxy: &structs.ServiceDefinitionConnectProxy{
  4448  						ExecMode: "daemon",
  4449  						Command:  []string{"awesome-proxy"},
  4450  						Config: map[string]interface{}{
  4451  							"foo": "qux",
  4452  						},
  4453  					},
  4454  				},
  4455  			},
  4456  			{
  4457  				ID:   "Kh81CPF6",
  4458  				Name: "Kh81CPF6-proxy",
  4459  				Port: 31471,
  4460  				Kind: "connect-proxy",
  4461  				Proxy: &structs.ConnectProxyConfig{
  4462  					DestinationServiceName: "6L6BVfgH",
  4463  					DestinationServiceID:   "6L6BVfgH-id",
  4464  					LocalServiceAddress:    "127.0.0.2",
  4465  					LocalServicePort:       23759,
  4466  					Config: map[string]interface{}{
  4467  						"cedGGtZf": "pWrUNiWw",
  4468  					},
  4469  					Upstreams: structs.Upstreams{
  4470  						{
  4471  							DestinationType: "service", // Default should be explicitly filled
  4472  							DestinationName: "KPtAj2cb",
  4473  							LocalBindPort:   4051,
  4474  							Config: map[string]interface{}{
  4475  								"kzRnZOyd": "nUNKoL8H",
  4476  							},
  4477  						},
  4478  						{
  4479  							DestinationType:      "prepared_query",
  4480  							DestinationNamespace: "9nakw0td",
  4481  							DestinationName:      "KSd8HsRl",
  4482  							LocalBindPort:        11884,
  4483  							LocalBindAddress:     "127.24.88.0",
  4484  						},
  4485  					},
  4486  				},
  4487  				Weights: &structs.Weights{
  4488  					Passing: 1,
  4489  					Warning: 1,
  4490  				},
  4491  			},
  4492  			{
  4493  				ID:      "dLOXpSCI",
  4494  				Name:    "o1ynPkp0",
  4495  				Tags:    []string{"nkwshvM5", "NTDWn3ek"},
  4496  				Address: "cOlSOhbp",
  4497  				Token:   "msy7iWER",
  4498  				Meta:    map[string]string{"mymeta": "data"},
  4499  				Port:    24237,
  4500  				Weights: &structs.Weights{
  4501  					Passing: 100,
  4502  					Warning: 1,
  4503  				},
  4504  				EnableTagOverride: true,
  4505  				Connect: &structs.ServiceConnect{
  4506  					Native: true,
  4507  				},
  4508  				Checks: structs.CheckTypes{
  4509  					&structs.CheckType{
  4510  						CheckID:    "Zv99e9Ka",
  4511  						Name:       "sgV4F7Pk",
  4512  						Notes:      "yP5nKbW0",
  4513  						Status:     "7oLMEyfu",
  4514  						ScriptArgs: []string{"5wEZtZpv", "0Ihyk8cS"},
  4515  						HTTP:       "KyDjGY9H",
  4516  						Header: map[string][]string{
  4517  							"gv5qefTz": {"5Olo2pMG", "PvvKWQU5"},
  4518  							"SHOVq1Vv": {"jntFhyym", "GYJh32pp"},
  4519  						},
  4520  						Method:                         "T66MFBfR",
  4521  						TCP:                            "bNnNfx2A",
  4522  						Interval:                       22224 * time.Second,
  4523  						DockerContainerID:              "ipgdFtjd",
  4524  						Shell:                          "omVZq7Sz",
  4525  						TLSSkipVerify:                  true,
  4526  						Timeout:                        18913 * time.Second,
  4527  						TTL:                            44743 * time.Second,
  4528  						DeregisterCriticalServiceAfter: 8482 * time.Second,
  4529  					},
  4530  					&structs.CheckType{
  4531  						CheckID:    "G79O6Mpr",
  4532  						Name:       "IEqrzrsd",
  4533  						Notes:      "SVqApqeM",
  4534  						Status:     "XXkVoZXt",
  4535  						ScriptArgs: []string{"wD05Bvao", "rLYB7kQC"},
  4536  						HTTP:       "kyICZsn8",
  4537  						Header: map[string][]string{
  4538  							"4ebP5vL4": {"G20SrL5Q", "DwPKlMbo"},
  4539  							"p2UI34Qz": {"UsG1D0Qh", "NHhRiB6s"},
  4540  						},
  4541  						Method:                         "ciYHWors",
  4542  						TCP:                            "FfvCwlqH",
  4543  						Interval:                       12356 * time.Second,
  4544  						DockerContainerID:              "HBndBU6R",
  4545  						Shell:                          "hVI33JjA",
  4546  						TLSSkipVerify:                  true,
  4547  						Timeout:                        38282 * time.Second,
  4548  						TTL:                            1181 * time.Second,
  4549  						DeregisterCriticalServiceAfter: 4992 * time.Second,
  4550  					},
  4551  					&structs.CheckType{
  4552  						CheckID:    "RMi85Dv8",
  4553  						Name:       "iehanzuq",
  4554  						Status:     "rCvn53TH",
  4555  						Notes:      "fti5lfF3",
  4556  						ScriptArgs: []string{"16WRUmwS", "QWk7j7ae"},
  4557  						HTTP:       "dl3Fgme3",
  4558  						Header: map[string][]string{
  4559  							"rjm4DEd3": {"2m3m2Fls"},
  4560  							"l4HwQ112": {"fk56MNlo", "dhLK56aZ"},
  4561  						},
  4562  						Method:                         "9afLm3Mj",
  4563  						TCP:                            "fjiLFqVd",
  4564  						Interval:                       23926 * time.Second,
  4565  						DockerContainerID:              "dO5TtRHk",
  4566  						Shell:                          "e6q2ttES",
  4567  						TLSSkipVerify:                  true,
  4568  						Timeout:                        38483 * time.Second,
  4569  						TTL:                            10943 * time.Second,
  4570  						DeregisterCriticalServiceAfter: 68787 * time.Second,
  4571  					},
  4572  				},
  4573  			},
  4574  		},
  4575  		SerfAdvertiseAddrLAN: tcpAddr("17.99.29.16:8301"),
  4576  		SerfAdvertiseAddrWAN: tcpAddr("78.63.37.19:8302"),
  4577  		SerfBindAddrLAN:      tcpAddr("99.43.63.15:8301"),
  4578  		SerfBindAddrWAN:      tcpAddr("67.88.33.19:8302"),
  4579  		SessionTTLMin:        26627 * time.Second,
  4580  		SkipLeaveOnInt:       true,
  4581  		StartJoinAddrsLAN:    []string{"LR3hGDoG", "MwVpZ4Up"},
  4582  		StartJoinAddrsWAN:    []string{"EbFSc3nA", "kwXTh623"},
  4583  		SyslogFacility:       "hHv79Uia",
  4584  		Telemetry: lib.TelemetryConfig{
  4585  			CirconusAPIApp:                     "p4QOTe9j",
  4586  			CirconusAPIToken:                   "E3j35V23",
  4587  			CirconusAPIURL:                     "mEMjHpGg",
  4588  			CirconusBrokerID:                   "BHlxUhed",
  4589  			CirconusBrokerSelectTag:            "13xy1gHm",
  4590  			CirconusCheckDisplayName:           "DRSlQR6n",
  4591  			CirconusCheckForceMetricActivation: "Ua5FGVYf",
  4592  			CirconusCheckID:                    "kGorutad",
  4593  			CirconusCheckInstanceID:            "rwoOL6R4",
  4594  			CirconusCheckSearchTag:             "ovT4hT4f",
  4595  			CirconusCheckTags:                  "prvO4uBl",
  4596  			CirconusSubmissionInterval:         "DolzaflP",
  4597  			CirconusSubmissionURL:              "gTcbS93G",
  4598  			DisableHostname:                    true,
  4599  			DogstatsdAddr:                      "0wSndumK",
  4600  			DogstatsdTags:                      []string{"3N81zSUB", "Xtj8AnXZ"},
  4601  			FilterDefault:                      true,
  4602  			AllowedPrefixes:                    []string{"oJotS8XJ"},
  4603  			BlockedPrefixes:                    []string{"cazlEhGn"},
  4604  			MetricsPrefix:                      "ftO6DySn",
  4605  			PrometheusRetentionTime:            15 * time.Second,
  4606  			StatsdAddr:                         "drce87cy",
  4607  			StatsiteAddr:                       "HpFwKB8R",
  4608  		},
  4609  		TLSCipherSuites:             []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
  4610  		TLSMinVersion:               "pAOWafkR",
  4611  		TLSPreferServerCipherSuites: true,
  4612  		TaggedAddresses: map[string]string{
  4613  			"7MYgHrYH": "dALJAhLD",
  4614  			"h6DdBy6K": "ebrr9zZ8",
  4615  			"lan":      "17.99.29.16",
  4616  			"wan":      "78.63.37.19",
  4617  		},
  4618  		TranslateWANAddrs:    true,
  4619  		UIDir:                "11IFzAUn",
  4620  		UnixSocketUser:       "E0nB1DwA",
  4621  		UnixSocketGroup:      "8pFodrV8",
  4622  		UnixSocketMode:       "E8sAwOv4",
  4623  		VerifyIncoming:       true,
  4624  		VerifyIncomingHTTPS:  true,
  4625  		VerifyIncomingRPC:    true,
  4626  		VerifyOutgoing:       true,
  4627  		VerifyServerHostname: true,
  4628  		Watches: []map[string]interface{}{
  4629  			map[string]interface{}{
  4630  				"type":       "key",
  4631  				"datacenter": "GyE6jpeW",
  4632  				"key":        "j9lF1Tve",
  4633  				"handler":    "90N7S4LN",
  4634  			},
  4635  			map[string]interface{}{
  4636  				"type":       "keyprefix",
  4637  				"datacenter": "fYrl3F5d",
  4638  				"key":        "sl3Dffu7",
  4639  				"args":       []interface{}{"dltjDJ2a", "flEa7C2d"},
  4640  			},
  4641  		},
  4642  		WatchSoftLimit: consul.DefaultSoftWatchLimit,
  4643  	}
  4644  
  4645  	warns := []string{
  4646  		`The 'acl_datacenter' field is deprecated. Use the 'primary_datacenter' field instead.`,
  4647  		`bootstrap_expect > 0: expecting 53 servers`,
  4648  	}
  4649  
  4650  	// ensure that all fields are set to unique non-zero values
  4651  	// todo(fs): This currently fails since ServiceDefinition.Check is not used
  4652  	// todo(fs): not sure on how to work around this. Possible options are:
  4653  	// todo(fs):  * move first check into the Check field
  4654  	// todo(fs):  * ignore the Check field
  4655  	// todo(fs): both feel like a hack
  4656  	if err := nonZero("RuntimeConfig", nil, want); err != nil {
  4657  		t.Log(err)
  4658  	}
  4659  
  4660  	for format, data := range src {
  4661  		t.Run(format, func(t *testing.T) {
  4662  			// parse the flags since this is the only way we can set the
  4663  			// DevMode flag
  4664  			var flags Flags
  4665  			fs := flag.NewFlagSet("", flag.ContinueOnError)
  4666  			AddFlags(fs, &flags)
  4667  			if err := fs.Parse(flagSrc); err != nil {
  4668  				t.Fatalf("ParseFlags: %s", err)
  4669  			}
  4670  
  4671  			// ensure that all fields are set to unique non-zero values
  4672  			// if err := nonZero("Config", nil, c); err != nil {
  4673  			// 	t.Fatal(err)
  4674  			// }
  4675  
  4676  			b, err := NewBuilder(flags)
  4677  			if err != nil {
  4678  				t.Fatalf("NewBuilder: %s", err)
  4679  			}
  4680  			b.Sources = append(b.Sources, Source{Name: "full." + format, Data: data})
  4681  			b.Tail = append(b.Tail, tail[format]...)
  4682  			b.Tail = append(b.Tail, VersionSource("JNtPSav3", "R909Hblt", "ZT1JOQLn"))
  4683  
  4684  			// construct the runtime config
  4685  			rt, err := b.Build()
  4686  			if err != nil {
  4687  				t.Fatalf("Build: %s", err)
  4688  			}
  4689  
  4690  			// verify that all fields are set
  4691  			if !verify.Values(t, "runtime_config", rt, want) {
  4692  				t.FailNow()
  4693  			}
  4694  
  4695  			// at this point we have confirmed that the parsing worked
  4696  			// for all fields but the validation will fail since certain
  4697  			// combinations are not allowed. Since it is not possible to have
  4698  			// all fields with non-zero values and to have a valid configuration
  4699  			// we are patching a handful of safe fields to make validation pass.
  4700  			rt.Bootstrap = false
  4701  			rt.DevMode = false
  4702  			rt.EnableUI = false
  4703  			rt.SegmentName = ""
  4704  			rt.Segments = nil
  4705  
  4706  			// validate the runtime config
  4707  			if err := b.Validate(rt); err != nil {
  4708  				t.Fatalf("Validate: %s", err)
  4709  			}
  4710  
  4711  			// check the warnings
  4712  			if got, want := b.Warnings, warns; !verify.Values(t, "warnings", got, want) {
  4713  				t.FailNow()
  4714  			}
  4715  		})
  4716  	}
  4717  }
  4718  
  4719  // nonZero verifies recursively that all fields are set to unique,
  4720  // non-zero and non-nil values.
  4721  //
  4722  // struct: check all fields recursively
  4723  // slice: check len > 0 and all values recursively
  4724  // ptr: check not nil
  4725  // bool: check not zero (cannot check uniqueness)
  4726  // string, int, uint: check not zero and unique
  4727  // other: error
  4728  func nonZero(name string, uniq map[interface{}]string, v interface{}) error {
  4729  	if v == nil {
  4730  		return fmt.Errorf("%q is nil", name)
  4731  	}
  4732  
  4733  	if uniq == nil {
  4734  		uniq = map[interface{}]string{}
  4735  	}
  4736  
  4737  	isUnique := func(v interface{}) error {
  4738  		if other := uniq[v]; other != "" {
  4739  			return fmt.Errorf("%q and %q both use value %q", name, other, v)
  4740  		}
  4741  		uniq[v] = name
  4742  		return nil
  4743  	}
  4744  
  4745  	val, typ := reflect.ValueOf(v), reflect.TypeOf(v)
  4746  	// fmt.Printf("%s: %T\n", name, v)
  4747  	switch typ.Kind() {
  4748  	case reflect.Struct:
  4749  		for i := 0; i < typ.NumField(); i++ {
  4750  			f := typ.Field(i)
  4751  			fieldname := fmt.Sprintf("%s.%s", name, f.Name)
  4752  			err := nonZero(fieldname, uniq, val.Field(i).Interface())
  4753  			if err != nil {
  4754  				return err
  4755  			}
  4756  		}
  4757  
  4758  	case reflect.Slice:
  4759  		if val.Len() == 0 {
  4760  			return fmt.Errorf("%q is empty slice", name)
  4761  		}
  4762  		for i := 0; i < val.Len(); i++ {
  4763  			elemname := fmt.Sprintf("%s[%d]", name, i)
  4764  			err := nonZero(elemname, uniq, val.Index(i).Interface())
  4765  			if err != nil {
  4766  				return err
  4767  			}
  4768  		}
  4769  
  4770  	case reflect.Map:
  4771  		if val.Len() == 0 {
  4772  			return fmt.Errorf("%q is empty map", name)
  4773  		}
  4774  		for _, key := range val.MapKeys() {
  4775  			keyname := fmt.Sprintf("%s[%s]", name, key.String())
  4776  			if err := nonZero(keyname, uniq, key.Interface()); err != nil {
  4777  				if strings.Contains(err.Error(), "is zero value") {
  4778  					return fmt.Errorf("%q has zero value map key", name)
  4779  				}
  4780  				return err
  4781  			}
  4782  			if err := nonZero(keyname, uniq, val.MapIndex(key).Interface()); err != nil {
  4783  				return err
  4784  			}
  4785  		}
  4786  
  4787  	case reflect.Bool:
  4788  		if val.Bool() != true {
  4789  			return fmt.Errorf("%q is zero value", name)
  4790  		}
  4791  		// do not test bool for uniqueness since there are only two values
  4792  
  4793  	case reflect.String:
  4794  		if val.Len() == 0 {
  4795  			return fmt.Errorf("%q is zero value", name)
  4796  		}
  4797  		return isUnique(v)
  4798  
  4799  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  4800  		if val.Int() == 0 {
  4801  			return fmt.Errorf("%q is zero value", name)
  4802  		}
  4803  		return isUnique(v)
  4804  
  4805  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  4806  		if val.Uint() == 0 {
  4807  			return fmt.Errorf("%q is zero value", name)
  4808  		}
  4809  		return isUnique(v)
  4810  
  4811  	case reflect.Float32, reflect.Float64:
  4812  		if val.Float() == 0 {
  4813  			return fmt.Errorf("%q is zero value", name)
  4814  		}
  4815  		return isUnique(v)
  4816  
  4817  	case reflect.Ptr:
  4818  		if val.IsNil() {
  4819  			return fmt.Errorf("%q is nil", name)
  4820  		}
  4821  		return nonZero("*"+name, uniq, val.Elem().Interface())
  4822  
  4823  	default:
  4824  		return fmt.Errorf("%T is not supported", v)
  4825  	}
  4826  	return nil
  4827  }
  4828  
  4829  func TestNonZero(t *testing.T) {
  4830  	var empty string
  4831  
  4832  	tests := []struct {
  4833  		desc string
  4834  		v    interface{}
  4835  		err  error
  4836  	}{
  4837  		{"nil", nil, errors.New(`"x" is nil`)},
  4838  		{"zero bool", false, errors.New(`"x" is zero value`)},
  4839  		{"zero string", "", errors.New(`"x" is zero value`)},
  4840  		{"zero int", int(0), errors.New(`"x" is zero value`)},
  4841  		{"zero int8", int8(0), errors.New(`"x" is zero value`)},
  4842  		{"zero int16", int16(0), errors.New(`"x" is zero value`)},
  4843  		{"zero int32", int32(0), errors.New(`"x" is zero value`)},
  4844  		{"zero int64", int64(0), errors.New(`"x" is zero value`)},
  4845  		{"zero uint", uint(0), errors.New(`"x" is zero value`)},
  4846  		{"zero uint8", uint8(0), errors.New(`"x" is zero value`)},
  4847  		{"zero uint16", uint16(0), errors.New(`"x" is zero value`)},
  4848  		{"zero uint32", uint32(0), errors.New(`"x" is zero value`)},
  4849  		{"zero uint64", uint64(0), errors.New(`"x" is zero value`)},
  4850  		{"zero float32", float32(0), errors.New(`"x" is zero value`)},
  4851  		{"zero float64", float64(0), errors.New(`"x" is zero value`)},
  4852  		{"ptr to zero value", &empty, errors.New(`"*x" is zero value`)},
  4853  		{"empty slice", []string{}, errors.New(`"x" is empty slice`)},
  4854  		{"slice with zero value", []string{""}, errors.New(`"x[0]" is zero value`)},
  4855  		{"empty map", map[string]string{}, errors.New(`"x" is empty map`)},
  4856  		{"map with zero value key", map[string]string{"": "y"}, errors.New(`"x" has zero value map key`)},
  4857  		{"map with zero value elem", map[string]string{"y": ""}, errors.New(`"x[y]" is zero value`)},
  4858  		{"struct with nil field", struct{ Y *int }{}, errors.New(`"x.Y" is nil`)},
  4859  		{"struct with zero value field", struct{ Y string }{}, errors.New(`"x.Y" is zero value`)},
  4860  		{"struct with empty array", struct{ Y []string }{}, errors.New(`"x.Y" is empty slice`)},
  4861  	}
  4862  
  4863  	for _, tt := range tests {
  4864  		t.Run(tt.desc, func(t *testing.T) {
  4865  			if got, want := nonZero("x", nil, tt.v), tt.err; !reflect.DeepEqual(got, want) {
  4866  				t.Fatalf("got error %v want %v", got, want)
  4867  			}
  4868  		})
  4869  	}
  4870  }
  4871  
  4872  func TestConfigDecodeBytes(t *testing.T) {
  4873  	t.Parallel()
  4874  	// Test with some input
  4875  	src := []byte("abc")
  4876  	key := base64.StdEncoding.EncodeToString(src)
  4877  
  4878  	result, err := decodeBytes(key)
  4879  	if err != nil {
  4880  		t.Fatalf("err: %s", err)
  4881  	}
  4882  
  4883  	if !bytes.Equal(src, result) {
  4884  		t.Fatalf("bad: %#v", result)
  4885  	}
  4886  
  4887  	// Test with no input
  4888  	result, err = decodeBytes("")
  4889  	if err != nil {
  4890  		t.Fatalf("err: %s", err)
  4891  	}
  4892  
  4893  	if len(result) > 0 {
  4894  		t.Fatalf("bad: %#v", result)
  4895  	}
  4896  }
  4897  
  4898  func TestSanitize(t *testing.T) {
  4899  	rt := RuntimeConfig{
  4900  		BindAddr:             &net.IPAddr{IP: net.ParseIP("127.0.0.1")},
  4901  		SerfAdvertiseAddrLAN: &net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
  4902  		DNSAddrs: []net.Addr{
  4903  			&net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
  4904  			&net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
  4905  		},
  4906  		DNSSOA: RuntimeSOAConfig{Refresh: 3600, Retry: 600, Expire: 86400, Minttl: 0},
  4907  		HTTPAddrs: []net.Addr{
  4908  			&net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
  4909  			&net.UnixAddr{Name: "/var/run/foo"},
  4910  		},
  4911  		ConsulCoordinateUpdatePeriod: 15 * time.Second,
  4912  		RetryJoinLAN: []string{
  4913  			"foo=bar key=baz secret=boom bang=bar",
  4914  		},
  4915  		RetryJoinWAN: []string{
  4916  			"wan_foo=bar wan_key=baz wan_secret=boom wan_bang=bar",
  4917  		},
  4918  		Services: []*structs.ServiceDefinition{
  4919  			&structs.ServiceDefinition{
  4920  				Name:  "foo",
  4921  				Token: "bar",
  4922  				Check: structs.CheckType{
  4923  					Name: "blurb",
  4924  				},
  4925  				Weights: &structs.Weights{
  4926  					Passing: 67,
  4927  					Warning: 3,
  4928  				},
  4929  			},
  4930  		},
  4931  		Checks: []*structs.CheckDefinition{
  4932  			&structs.CheckDefinition{
  4933  				Name:  "zoo",
  4934  				Token: "zope",
  4935  			},
  4936  		},
  4937  	}
  4938  
  4939  	rtJSON := `{
  4940  		"ACLAgentMasterToken": "hidden",
  4941  		"ACLAgentToken": "hidden",
  4942  		"ACLDatacenter": "",
  4943  		"ACLDefaultPolicy": "",
  4944  		"ACLDisabledTTL": "0s",
  4945  		"ACLDownPolicy": "",
  4946  		"ACLEnableKeyListPolicy": false,
  4947  		"ACLEnableTokenPersistence": false,
  4948  		"ACLEnforceVersion8": false,
  4949  		"ACLMasterToken": "hidden",
  4950  		"ACLPolicyTTL": "0s",
  4951  		"ACLReplicationToken": "hidden",
  4952  		"ACLTokenReplication": false,
  4953  		"ACLTokenTTL": "0s",
  4954  		"ACLToken": "hidden",
  4955  		"ACLsEnabled": false,
  4956  		"AEInterval": "0s",
  4957  		"AdvertiseAddrLAN": "",
  4958  		"AdvertiseAddrWAN": "",
  4959  		"AutopilotCleanupDeadServers": false,
  4960  		"AutopilotDisableUpgradeMigration": false,
  4961  		"AutopilotLastContactThreshold": "0s",
  4962  		"AutopilotMaxTrailingLogs": 0,
  4963  		"AutopilotRedundancyZoneTag": "",
  4964  		"AutopilotServerStabilizationTime": "0s",
  4965  		"AutopilotUpgradeVersionTag": "",
  4966  		"BindAddr": "127.0.0.1",
  4967  		"Bootstrap": false,
  4968  		"BootstrapExpect": 0,
  4969  		"CAFile": "",
  4970  		"CAPath": "",
  4971  		"CertFile": "",
  4972  		"CheckDeregisterIntervalMin": "0s",
  4973  		"CheckReapInterval": "0s",
  4974  		"CheckUpdateInterval": "0s",
  4975  		"Checks": [{
  4976  			"AliasNode": "",
  4977  			"AliasService": "",
  4978  			"DeregisterCriticalServiceAfter": "0s",
  4979  			"DockerContainerID": "",
  4980  			"GRPC": "",
  4981  			"GRPCUseTLS": false,
  4982  			"HTTP": "",
  4983  			"Header": {},
  4984  			"ID": "",
  4985  			"Interval": "0s",
  4986  			"Method": "",
  4987  			"Name": "zoo",
  4988  			"Notes": "",
  4989  			"ScriptArgs": [],
  4990  			"ServiceID": "",
  4991  			"Shell": "",
  4992  			"Status": "",
  4993  			"TCP": "",
  4994  			"TLSSkipVerify": false,
  4995  			"TTL": "0s",
  4996  			"Timeout": "0s",
  4997  			"Token": "hidden"
  4998  		}],
  4999  		"ClientAddrs": [],
  5000  		"ConnectCAConfig": {},
  5001  		"ConnectCAProvider": "",
  5002  		"ConnectEnabled": false,
  5003  		"ConnectProxyAllowManagedAPIRegistration": false,
  5004  		"ConnectProxyAllowManagedRoot": false,
  5005  		"ConnectProxyBindMaxPort": 0,
  5006  		"ConnectProxyBindMinPort": 0,
  5007  		"ConnectProxyDefaultConfig": {},
  5008  		"ConnectProxyDefaultDaemonCommand": [],
  5009  		"ConnectProxyDefaultExecMode": "",
  5010  		"ConnectProxyDefaultScriptCommand": [],
  5011  		"ConnectSidecarMaxPort": 0,
  5012  		"ConnectSidecarMinPort": 0,
  5013  		"ConnectTestCALeafRootChangeSpread": "0s",
  5014  		"ConnectTestDisableManagedProxies": false,
  5015  		"ConsulCoordinateUpdateBatchSize": 0,
  5016  		"ConsulCoordinateUpdateMaxBatches": 0,
  5017  		"ConsulCoordinateUpdatePeriod": "15s",
  5018  		"ConsulRaftElectionTimeout": "0s",
  5019  		"ConsulRaftHeartbeatTimeout": "0s",
  5020  		"ConsulRaftLeaderLeaseTimeout": "0s",
  5021  		"GossipLANGossipInterval": "0s",
  5022  		"GossipLANGossipNodes": 0,
  5023  		"GossipLANProbeInterval": "0s",
  5024  		"GossipLANProbeTimeout": "0s",
  5025  		"GossipLANRetransmitMult": 0,
  5026  		"GossipLANSuspicionMult": 0,
  5027  		"GossipWANGossipInterval": "0s",
  5028  		"GossipWANGossipNodes": 0,
  5029  		"GossipWANProbeInterval": "0s",
  5030  		"GossipWANProbeTimeout": "0s",
  5031  		"GossipWANRetransmitMult": 0,
  5032  		"GossipWANSuspicionMult": 0,
  5033  		"ConsulServerHealthInterval": "0s",
  5034  		"DNSARecordLimit": 0,
  5035  		"DNSAddrs": [
  5036  			"tcp://1.2.3.4:5678",
  5037  			"udp://1.2.3.4:5678"
  5038  		],
  5039  		"DNSAllowStale": false,
  5040  		"DNSDisableCompression": false,
  5041  		"DNSDomain": "",
  5042  		"DNSEnableTruncate": false,
  5043  		"DNSMaxStale": "0s",
  5044  		"DNSNodeMetaTXT": false,
  5045  		"DNSNodeTTL": "0s",
  5046  		"DNSOnlyPassing": false,
  5047  		"DNSPort": 0,
  5048  		"DNSRecursorTimeout": "0s",
  5049  		"DNSRecursors": [],
  5050  		"DNSServiceTTL": {},
  5051  		"DNSSOA": {
  5052  			"Refresh": 3600,
  5053  			"Retry": 600,
  5054  			"Expire": 86400,
  5055  			"Minttl": 0
  5056  		},
  5057  		"DNSUDPAnswerLimit": 0,
  5058  		"DNSUseCache": false,
  5059  		"DNSCacheMaxAge": "0s",
  5060  		"DataDir": "",
  5061  		"Datacenter": "",
  5062  		"DevMode": false,
  5063  		"DisableAnonymousSignature": false,
  5064  		"DisableCoordinates": false,
  5065  		"DisableHTTPUnprintableCharFilter": false,
  5066  		"DisableHostNodeID": false,
  5067  		"DisableKeyringFile": false,
  5068  		"DisableRemoteExec": false,
  5069  		"DisableUpdateCheck": false,
  5070  		"DiscardCheckOutput": false,
  5071  		"DiscoveryMaxStale": "0s",
  5072  		"EnableAgentTLSForChecks": false,
  5073  		"EnableDebug": false,
  5074  		"EnableLocalScriptChecks": false,
  5075  		"EnableRemoteScriptChecks": false,
  5076  		"EnableSyslog": false,
  5077  		"EnableUI": false,
  5078  		"EncryptKey": "hidden",
  5079  		"EncryptVerifyIncoming": false,
  5080  		"EncryptVerifyOutgoing": false,
  5081  		"GRPCAddrs": [],
  5082  		"GRPCPort": 0,
  5083  		"HTTPAddrs": [
  5084  			"tcp://1.2.3.4:5678",
  5085  			"unix:///var/run/foo"
  5086  		],
  5087  		"HTTPBlockEndpoints": [],
  5088  		"HTTPPort": 0,
  5089  		"HTTPResponseHeaders": {},
  5090  		"HTTPSAddrs": [],
  5091  		"HTTPSPort": 0,
  5092  		"KeyFile": "hidden",
  5093  		"LeaveDrainTime": "0s",
  5094  		"LeaveOnTerm": false,
  5095  		"LogLevel": "",
  5096  		"LogFile": "",
  5097  		"LogRotateBytes": 0,
  5098  		"LogRotateDuration": "0s",
  5099  		"NodeID": "",
  5100  		"NodeMeta": {},
  5101  		"NodeName": "",
  5102  		"NonVotingServer": false,
  5103  		"PidFile": "",
  5104  		"PrimaryDatacenter": "",
  5105  		"RPCAdvertiseAddr": "",
  5106  		"RPCBindAddr": "",
  5107  		"RPCHoldTimeout": "0s",
  5108  		"RPCMaxBurst": 0,
  5109  		"RPCProtocol": 0,
  5110  		"RPCRateLimit": 0,
  5111  		"RaftProtocol": 0,
  5112  		"RaftSnapshotInterval": "0s",
  5113  		"RaftSnapshotThreshold": 0,
  5114  		"ReconnectTimeoutLAN": "0s",
  5115  		"ReconnectTimeoutWAN": "0s",
  5116  		"RejoinAfterLeave": false,
  5117  		"RetryJoinIntervalLAN": "0s",
  5118  		"RetryJoinIntervalWAN": "0s",
  5119  		"RetryJoinLAN": [
  5120  			"foo=bar key=hidden secret=hidden bang=bar"
  5121  		],
  5122  		"RetryJoinMaxAttemptsLAN": 0,
  5123  		"RetryJoinMaxAttemptsWAN": 0,
  5124  		"RetryJoinWAN": [
  5125  			"wan_foo=bar wan_key=hidden wan_secret=hidden wan_bang=bar"
  5126  		],
  5127  		"Revision": "",
  5128  		"SegmentLimit": 0,
  5129  		"SegmentName": "",
  5130  		"SegmentNameLimit": 0,
  5131  		"Segments": [],
  5132  		"SerfAdvertiseAddrLAN": "tcp://1.2.3.4:5678",
  5133  		"SerfAdvertiseAddrWAN": "",
  5134  		"SerfBindAddrLAN": "",
  5135  		"SerfBindAddrWAN": "",
  5136  		"SerfPortLAN": 0,
  5137  		"SerfPortWAN": 0,
  5138  		"ServerMode": false,
  5139  		"ServerName": "",
  5140  		"ServerPort": 0,
  5141  		"Services": [{
  5142  			"Address": "",
  5143  			"Check": {
  5144  				"AliasNode": "",
  5145  				"AliasService": "",
  5146  				"CheckID": "",
  5147  				"DeregisterCriticalServiceAfter": "0s",
  5148  				"DockerContainerID": "",
  5149  				"GRPC": "",
  5150  				"GRPCUseTLS": false,
  5151  				"HTTP": "",
  5152  				"Header": {},
  5153  				"Interval": "0s",
  5154  				"Method": "",
  5155  				"Name": "blurb",
  5156  				"Notes": "",
  5157  				"ScriptArgs": [],
  5158  				"Shell": "",
  5159  				"Status": "",
  5160  				"TCP": "",
  5161  				"TLSSkipVerify": false,
  5162  				"TTL": "0s",
  5163  				"Timeout": "0s"
  5164  			},
  5165  			"Checks": [],
  5166  			"Connect": null,
  5167  			"EnableTagOverride": false,
  5168  			"ID": "",
  5169  			"Kind": "",
  5170  			"Meta": {},
  5171  			"Name": "foo",
  5172  			"Port": 0,
  5173  			"Proxy": null,
  5174  			"ProxyDestination": "",
  5175  			"Tags": [],
  5176  			"Token": "hidden",
  5177  			"Weights": {
  5178  				"Passing": 67,
  5179  				"Warning": 3
  5180  			}
  5181  		}],
  5182  		"SessionTTLMin": "0s",
  5183  		"SkipLeaveOnInt": false,
  5184  		"StartJoinAddrsLAN": [],
  5185  		"StartJoinAddrsWAN": [],
  5186  		"SyncCoordinateIntervalMin": "0s",
  5187  		"SyncCoordinateRateTarget": 0,
  5188  		"SyslogFacility": "",
  5189  		"TLSCipherSuites": [],
  5190  		"TLSMinVersion": "",
  5191  		"TLSPreferServerCipherSuites": false,
  5192  		"TaggedAddresses": {},
  5193  		"Telemetry": {
  5194  			"AllowedPrefixes": [],
  5195  			"BlockedPrefixes": [],
  5196  			"CirconusAPIApp": "",
  5197  			"CirconusAPIToken": "hidden",
  5198  			"CirconusAPIURL": "",
  5199  			"CirconusBrokerID": "",
  5200  			"CirconusBrokerSelectTag": "",
  5201  			"CirconusCheckDisplayName": "",
  5202  			"CirconusCheckForceMetricActivation": "",
  5203  			"CirconusCheckID": "",
  5204  			"CirconusCheckInstanceID": "",
  5205  			"CirconusCheckSearchTag": "",
  5206  			"CirconusCheckTags": "",
  5207  			"CirconusSubmissionInterval": "",
  5208  			"CirconusSubmissionURL": "",
  5209  			"DisableHostname": false,
  5210  			"DogstatsdAddr": "",
  5211  			"DogstatsdTags": [],
  5212  			"FilterDefault": false,
  5213  			"MetricsPrefix": "",
  5214  			"PrometheusRetentionTime": "0s",
  5215  			"StatsdAddr": "",
  5216  			"StatsiteAddr": ""
  5217  		},
  5218  		"TranslateWANAddrs": false,
  5219  		"UIDir": "",
  5220  		"UnixSocketGroup": "",
  5221  		"UnixSocketMode": "",
  5222  		"UnixSocketUser": "",
  5223  		"VerifyIncoming": false,
  5224  		"VerifyIncomingHTTPS": false,
  5225  		"VerifyIncomingRPC": false,
  5226  		"VerifyOutgoing": false,
  5227  		"VerifyServerHostname": false,
  5228  		"Version": "",
  5229  		"VersionPrerelease": "",
  5230  		"Watches": [],
  5231  		"AllowWriteHTTPFrom": []
  5232  		"WatchSoftLimit": 0
  5233  	}`
  5234  	b, err := json.MarshalIndent(rt.Sanitized(), "", "    ")
  5235  	if err != nil {
  5236  		t.Fatal(err)
  5237  	}
  5238  	require.JSONEq(t, rtJSON, string(b))
  5239  }
  5240  
  5241  func TestRuntime_apiAddresses(t *testing.T) {
  5242  	rt := RuntimeConfig{
  5243  		HTTPAddrs: []net.Addr{
  5244  			&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5678},
  5245  			&net.UnixAddr{Name: "/var/run/foo"},
  5246  		},
  5247  		HTTPSAddrs: []net.Addr{
  5248  			&net.TCPAddr{IP: net.ParseIP("198.18.0.2"), Port: 5678},
  5249  		}}
  5250  
  5251  	unixAddrs, httpAddrs, httpsAddrs := rt.apiAddresses(1)
  5252  
  5253  	require.Len(t, unixAddrs, 1)
  5254  	require.Len(t, httpAddrs, 1)
  5255  	require.Len(t, httpsAddrs, 1)
  5256  
  5257  	require.Equal(t, "/var/run/foo", unixAddrs[0])
  5258  	require.Equal(t, "198.18.0.1:5678", httpAddrs[0])
  5259  	require.Equal(t, "198.18.0.2:5678", httpsAddrs[0])
  5260  }
  5261  
  5262  func TestRuntime_APIConfigHTTPS(t *testing.T) {
  5263  	rt := RuntimeConfig{
  5264  		HTTPAddrs: []net.Addr{
  5265  			&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5678},
  5266  			&net.UnixAddr{Name: "/var/run/foo"},
  5267  		},
  5268  		HTTPSAddrs: []net.Addr{
  5269  			&net.TCPAddr{IP: net.ParseIP("198.18.0.2"), Port: 5678},
  5270  		},
  5271  		Datacenter:     "dc-test",
  5272  		CAFile:         "/etc/consul/ca.crt",
  5273  		CAPath:         "/etc/consul/ca.dir",
  5274  		CertFile:       "/etc/consul/server.crt",
  5275  		KeyFile:        "/etc/consul/ssl/server.key",
  5276  		VerifyOutgoing: false,
  5277  	}
  5278  
  5279  	cfg, err := rt.APIConfig(false)
  5280  	require.NoError(t, err)
  5281  	require.Equal(t, "198.18.0.2:5678", cfg.Address)
  5282  	require.Equal(t, "https", cfg.Scheme)
  5283  	require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile)
  5284  	require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath)
  5285  	require.Equal(t, "", cfg.TLSConfig.CertFile)
  5286  	require.Equal(t, "", cfg.TLSConfig.KeyFile)
  5287  	require.Equal(t, rt.Datacenter, cfg.Datacenter)
  5288  	require.Equal(t, true, cfg.TLSConfig.InsecureSkipVerify)
  5289  
  5290  	rt.VerifyOutgoing = true
  5291  	cfg, err = rt.APIConfig(true)
  5292  	require.NoError(t, err)
  5293  	require.Equal(t, "198.18.0.2:5678", cfg.Address)
  5294  	require.Equal(t, "https", cfg.Scheme)
  5295  	require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile)
  5296  	require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath)
  5297  	require.Equal(t, rt.CertFile, cfg.TLSConfig.CertFile)
  5298  	require.Equal(t, rt.KeyFile, cfg.TLSConfig.KeyFile)
  5299  	require.Equal(t, rt.Datacenter, cfg.Datacenter)
  5300  	require.Equal(t, false, cfg.TLSConfig.InsecureSkipVerify)
  5301  }
  5302  
  5303  func TestRuntime_APIConfigHTTP(t *testing.T) {
  5304  	rt := RuntimeConfig{
  5305  		HTTPAddrs: []net.Addr{
  5306  			&net.UnixAddr{Name: "/var/run/foo"},
  5307  			&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5678},
  5308  		},
  5309  		Datacenter: "dc-test",
  5310  	}
  5311  
  5312  	cfg, err := rt.APIConfig(false)
  5313  	require.NoError(t, err)
  5314  	require.Equal(t, rt.Datacenter, cfg.Datacenter)
  5315  	require.Equal(t, "198.18.0.1:5678", cfg.Address)
  5316  	require.Equal(t, "http", cfg.Scheme)
  5317  	require.Equal(t, "", cfg.TLSConfig.CAFile)
  5318  	require.Equal(t, "", cfg.TLSConfig.CAPath)
  5319  	require.Equal(t, "", cfg.TLSConfig.CertFile)
  5320  	require.Equal(t, "", cfg.TLSConfig.KeyFile)
  5321  }
  5322  
  5323  func TestRuntime_APIConfigUNIX(t *testing.T) {
  5324  	rt := RuntimeConfig{
  5325  		HTTPAddrs: []net.Addr{
  5326  			&net.UnixAddr{Name: "/var/run/foo"},
  5327  		},
  5328  		Datacenter: "dc-test",
  5329  	}
  5330  
  5331  	cfg, err := rt.APIConfig(false)
  5332  	require.NoError(t, err)
  5333  	require.Equal(t, rt.Datacenter, cfg.Datacenter)
  5334  	require.Equal(t, "unix:///var/run/foo", cfg.Address)
  5335  	require.Equal(t, "http", cfg.Scheme)
  5336  	require.Equal(t, "", cfg.TLSConfig.CAFile)
  5337  	require.Equal(t, "", cfg.TLSConfig.CAPath)
  5338  	require.Equal(t, "", cfg.TLSConfig.CertFile)
  5339  	require.Equal(t, "", cfg.TLSConfig.KeyFile)
  5340  }
  5341  
  5342  func TestRuntime_APIConfigANYAddrV4(t *testing.T) {
  5343  	rt := RuntimeConfig{
  5344  		HTTPAddrs: []net.Addr{
  5345  			&net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 5678},
  5346  		},
  5347  		Datacenter: "dc-test",
  5348  	}
  5349  
  5350  	cfg, err := rt.APIConfig(false)
  5351  	require.NoError(t, err)
  5352  	require.Equal(t, rt.Datacenter, cfg.Datacenter)
  5353  	require.Equal(t, "127.0.0.1:5678", cfg.Address)
  5354  	require.Equal(t, "http", cfg.Scheme)
  5355  	require.Equal(t, "", cfg.TLSConfig.CAFile)
  5356  	require.Equal(t, "", cfg.TLSConfig.CAPath)
  5357  	require.Equal(t, "", cfg.TLSConfig.CertFile)
  5358  	require.Equal(t, "", cfg.TLSConfig.KeyFile)
  5359  }
  5360  
  5361  func TestRuntime_APIConfigANYAddrV6(t *testing.T) {
  5362  	rt := RuntimeConfig{
  5363  		HTTPAddrs: []net.Addr{
  5364  			&net.TCPAddr{IP: net.ParseIP("::"), Port: 5678},
  5365  		},
  5366  		Datacenter: "dc-test",
  5367  	}
  5368  
  5369  	cfg, err := rt.APIConfig(false)
  5370  	require.NoError(t, err)
  5371  	require.Equal(t, rt.Datacenter, cfg.Datacenter)
  5372  	require.Equal(t, "[::1]:5678", cfg.Address)
  5373  	require.Equal(t, "http", cfg.Scheme)
  5374  	require.Equal(t, "", cfg.TLSConfig.CAFile)
  5375  	require.Equal(t, "", cfg.TLSConfig.CAPath)
  5376  	require.Equal(t, "", cfg.TLSConfig.CertFile)
  5377  	require.Equal(t, "", cfg.TLSConfig.KeyFile)
  5378  }
  5379  
  5380  func TestRuntime_ClientAddress(t *testing.T) {
  5381  	rt := RuntimeConfig{
  5382  		HTTPAddrs: []net.Addr{
  5383  			&net.TCPAddr{IP: net.ParseIP("::"), Port: 5678},
  5384  			&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5679},
  5385  			&net.UnixAddr{Name: "/var/run/foo", Net: "unix"},
  5386  		},
  5387  		HTTPSAddrs: []net.Addr{
  5388  			&net.TCPAddr{IP: net.ParseIP("::"), Port: 5688},
  5389  			&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5689},
  5390  		},
  5391  	}
  5392  
  5393  	unix, http, https := rt.ClientAddress()
  5394  
  5395  	require.Equal(t, "unix:///var/run/foo", unix)
  5396  	require.Equal(t, "198.18.0.1:5679", http)
  5397  	require.Equal(t, "198.18.0.1:5689", https)
  5398  }
  5399  
  5400  func TestRuntime_ClientAddressAnyV4(t *testing.T) {
  5401  	rt := RuntimeConfig{
  5402  		HTTPAddrs: []net.Addr{
  5403  			&net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 5678},
  5404  			&net.UnixAddr{Name: "/var/run/foo", Net: "unix"},
  5405  		},
  5406  		HTTPSAddrs: []net.Addr{
  5407  			&net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 5688},
  5408  		},
  5409  	}
  5410  
  5411  	unix, http, https := rt.ClientAddress()
  5412  
  5413  	require.Equal(t, "unix:///var/run/foo", unix)
  5414  	require.Equal(t, "127.0.0.1:5678", http)
  5415  	require.Equal(t, "127.0.0.1:5688", https)
  5416  }
  5417  
  5418  func TestRuntime_ClientAddressAnyV6(t *testing.T) {
  5419  	rt := RuntimeConfig{
  5420  		HTTPAddrs: []net.Addr{
  5421  			&net.TCPAddr{IP: net.ParseIP("::"), Port: 5678},
  5422  			&net.UnixAddr{Name: "/var/run/foo", Net: "unix"},
  5423  		},
  5424  		HTTPSAddrs: []net.Addr{
  5425  			&net.TCPAddr{IP: net.ParseIP("::"), Port: 5688},
  5426  		},
  5427  	}
  5428  
  5429  	unix, http, https := rt.ClientAddress()
  5430  
  5431  	require.Equal(t, "unix:///var/run/foo", unix)
  5432  	require.Equal(t, "[::1]:5678", http)
  5433  	require.Equal(t, "[::1]:5688", https)
  5434  }
  5435  
  5436  func TestRuntime_ToTLSUtilConfig(t *testing.T) {
  5437  	c := &RuntimeConfig{
  5438  		VerifyIncoming:              true,
  5439  		VerifyIncomingRPC:           true,
  5440  		VerifyIncomingHTTPS:         true,
  5441  		VerifyOutgoing:              true,
  5442  		VerifyServerHostname:        true,
  5443  		CAFile:                      "a",
  5444  		CAPath:                      "b",
  5445  		CertFile:                    "c",
  5446  		KeyFile:                     "d",
  5447  		NodeName:                    "e",
  5448  		ServerName:                  "f",
  5449  		DNSDomain:                   "g",
  5450  		TLSMinVersion:               "tls12",
  5451  		TLSCipherSuites:             []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305},
  5452  		TLSPreferServerCipherSuites: true,
  5453  		EnableAgentTLSForChecks:     true,
  5454  	}
  5455  	r := c.ToTLSUtilConfig()
  5456  	require.Equal(t, c.VerifyIncoming, r.VerifyIncoming)
  5457  	require.Equal(t, c.VerifyIncomingRPC, r.VerifyIncomingRPC)
  5458  	require.Equal(t, c.VerifyIncomingHTTPS, r.VerifyIncomingHTTPS)
  5459  	require.Equal(t, c.VerifyOutgoing, r.VerifyOutgoing)
  5460  	require.Equal(t, c.VerifyServerHostname, r.VerifyServerHostname)
  5461  	require.Equal(t, c.CAFile, r.CAFile)
  5462  	require.Equal(t, c.CAPath, r.CAPath)
  5463  	require.Equal(t, c.CertFile, r.CertFile)
  5464  	require.Equal(t, c.KeyFile, r.KeyFile)
  5465  	require.Equal(t, c.NodeName, r.NodeName)
  5466  	require.Equal(t, c.ServerName, r.ServerName)
  5467  	require.Equal(t, c.DNSDomain, r.Domain)
  5468  	require.Equal(t, c.TLSMinVersion, r.TLSMinVersion)
  5469  	require.Equal(t, c.TLSCipherSuites, r.CipherSuites)
  5470  	require.Equal(t, c.TLSPreferServerCipherSuites, r.PreferServerCipherSuites)
  5471  	require.Equal(t, c.EnableAgentTLSForChecks, r.EnableAgentTLSForChecks)
  5472  }
  5473  
  5474  func splitIPPort(hostport string) (net.IP, int) {
  5475  	h, p, err := net.SplitHostPort(hostport)
  5476  	if err != nil {
  5477  		panic(err)
  5478  	}
  5479  	port, err := strconv.Atoi(p)
  5480  	if err != nil {
  5481  		panic(err)
  5482  	}
  5483  	return net.ParseIP(h), port
  5484  }
  5485  
  5486  func ipAddr(addr string) *net.IPAddr {
  5487  	return &net.IPAddr{IP: net.ParseIP(addr)}
  5488  }
  5489  
  5490  func tcpAddr(addr string) *net.TCPAddr {
  5491  	ip, port := splitIPPort(addr)
  5492  	return &net.TCPAddr{IP: ip, Port: port}
  5493  }
  5494  
  5495  func udpAddr(addr string) *net.UDPAddr {
  5496  	ip, port := splitIPPort(addr)
  5497  	return &net.UDPAddr{IP: ip, Port: port}
  5498  }
  5499  
  5500  func unixAddr(addr string) *net.UnixAddr {
  5501  	if !strings.HasPrefix(addr, "unix://") {
  5502  		panic("not a unix socket addr: " + addr)
  5503  	}
  5504  	return &net.UnixAddr{Net: "unix", Name: addr[len("unix://"):]}
  5505  }
  5506  
  5507  func writeFile(path string, data []byte) {
  5508  	if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil {
  5509  		panic(err)
  5510  	}
  5511  	if err := ioutil.WriteFile(path, data, 0640); err != nil {
  5512  		panic(err)
  5513  	}
  5514  }
  5515  
  5516  func cleanDir(path string) {
  5517  	root := path
  5518  	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
  5519  		if path == root {
  5520  			return nil
  5521  		}
  5522  		return os.RemoveAll(path)
  5523  	})
  5524  	if err != nil {
  5525  		panic(err)
  5526  	}
  5527  }
  5528  
  5529  func randomString(n int) string {
  5530  	s := ""
  5531  	for ; n > 0; n-- {
  5532  		s += "x"
  5533  	}
  5534  	return s
  5535  }
  5536  
  5537  func metaPairs(n int, format string) string {
  5538  	var s []string
  5539  	for i := 0; i < n; i++ {
  5540  		switch format {
  5541  		case "json":
  5542  			s = append(s, fmt.Sprintf(`"%d":"%d"`, i, i))
  5543  		case "hcl":
  5544  			s = append(s, fmt.Sprintf(`"%d"="%d"`, i, i))
  5545  		default:
  5546  			panic("invalid format: " + format)
  5547  		}
  5548  	}
  5549  	switch format {
  5550  	case "json":
  5551  		return strings.Join(s, ",")
  5552  	case "hcl":
  5553  		return strings.Join(s, " ")
  5554  	default:
  5555  		panic("invalid format: " + format)
  5556  	}
  5557  }