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