Add `consul snapshot decode` command (#20824)

Add snapshot decoding command
This commit is contained in:
Matt Keeler 2024-03-14 12:59:06 -04:00 committed by GitHub
parent e9029ccd7a
commit 8fcafb139c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 821 additions and 7 deletions

3
.changelog/20824.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
snapshot: Add `consul snapshot decode` CLI command to output a JSON object stream of all the snapshots data.
```

View File

@ -129,6 +129,7 @@ import (
exportedservices "github.com/hashicorp/consul/command/services/exportedservices"
svcsregister "github.com/hashicorp/consul/command/services/register"
"github.com/hashicorp/consul/command/snapshot"
snapdecode "github.com/hashicorp/consul/command/snapshot/decode"
snapinspect "github.com/hashicorp/consul/command/snapshot/inspect"
snaprestore "github.com/hashicorp/consul/command/snapshot/restore"
snapsave "github.com/hashicorp/consul/command/snapshot/save"
@ -276,6 +277,7 @@ func RegisteredCommands(ui cli.Ui) map[string]mcli.CommandFactory {
entry{"services export", func(ui cli.Ui) (cli.Command, error) { return svcsexport.New(ui), nil }},
entry{"services exported-services", func(ui cli.Ui) (cli.Command, error) { return exportedservices.New(ui), nil }},
entry{"snapshot", func(cli.Ui) (cli.Command, error) { return snapshot.New(), nil }},
entry{"snapshot decode", func(ui cli.Ui) (cli.Command, error) { return snapdecode.New(ui), nil }},
entry{"snapshot inspect", func(ui cli.Ui) (cli.Command, error) { return snapinspect.New(ui), nil }},
entry{"snapshot restore", func(ui cli.Ui) (cli.Command, error) { return snaprestore.New(ui), nil }},
entry{"snapshot save", func(ui cli.Ui) (cli.Command, error) { return snapsave.New(ui), nil }},

View File

@ -0,0 +1,218 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package decode
import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
"path"
"strings"
"github.com/hashicorp/consul-net-rpc/go-msgpack/codec"
"github.com/hashicorp/consul/agent/consul/fsm"
"github.com/hashicorp/consul/agent/consul/state"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/command/flags"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/proto/private/pbpeering"
"github.com/hashicorp/consul/snapshot"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-raftchunking"
"github.com/hashicorp/raft"
"github.com/mitchellh/cli"
)
var requestTypeZeroValues = map[structs.MessageType]func() any{
structs.RegisterRequestType: func() any { return new(structs.RegisterRequest) },
structs.KVSRequestType: func() any { return new(structs.KVSRequest) },
structs.SessionRequestType: func() any { return new(structs.SessionRequest) },
structs.TombstoneRequestType: func() any { return new(structs.TombstoneRequest) },
structs.CoordinateBatchUpdateType: func() any { return new(structs.Coordinates) },
structs.PreparedQueryRequestType: func() any { return new(structs.PreparedQueryRequest) },
structs.AutopilotRequestType: func() any { return new(structs.AutopilotSetConfigRequest) },
structs.IntentionRequestType: func() any { return new(structs.IntentionRequest) },
structs.ConnectCARequestType: func() any { return new(structs.CARequest) },
structs.ConnectCAProviderStateType: func() any { return new(structs.CAConsulProviderState) },
structs.ConnectCAConfigType: func() any { return new(structs.CAConfiguration) },
structs.IndexRequestType: func() any { return new(state.IndexEntry) },
structs.ACLTokenSetRequestType: func() any { return new(structs.ACLToken) },
structs.ACLPolicySetRequestType: func() any { return new(structs.ACLPolicy) },
structs.ConfigEntryRequestType: func() any { return new(structs.ConfigEntryRequest) },
structs.ACLRoleSetRequestType: func() any { return new(structs.ACLRole) },
structs.ACLBindingRuleSetRequestType: func() any { return new(structs.ACLBindingRule) },
structs.ACLAuthMethodSetRequestType: func() any { return new(structs.ACLAuthMethod) },
structs.ChunkingStateType: func() any { return new(raftchunking.State) },
structs.FederationStateRequestType: func() any { return new(structs.FederationStateRequest) },
structs.SystemMetadataRequestType: func() any { return new(structs.SystemMetadataEntry) },
structs.ServiceVirtualIPRequestType: func() any { return new(state.ServiceVirtualIP) },
structs.FreeVirtualIPRequestType: func() any { return new(state.FreeVirtualIP) },
structs.PeeringWriteType: func() any { return new(pbpeering.Peering) },
structs.PeeringTrustBundleWriteType: func() any { return new(pbpeering.PeeringTrustBundle) },
structs.PeeringSecretsWriteType: func() any { return new(pbpeering.PeeringSecrets) },
structs.ResourceOperationType: func() any { return new(pbresource.Resource) },
}
func New(ui cli.Ui) *cmd {
c := &cmd{UI: ui}
c.init()
return c
}
type cmd struct {
UI cli.Ui
flags *flag.FlagSet
help string
format string
encoder *json.Encoder
}
func (c *cmd) Write(p []byte) (n int, err error) {
s := string(p)
c.UI.Output(strings.TrimRight(s, "\n"))
return len(s), nil
}
func (c *cmd) init() {
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
c.help = flags.Usage(help, c.flags)
c.encoder = json.NewEncoder(c)
}
func (c *cmd) Run(args []string) int {
if err := c.flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
var file string
args = c.flags.Args()
switch len(args) {
case 0:
c.UI.Error("Missing FILE argument")
return 1
case 1:
file = args[0]
default:
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
return 1
}
// Open the file.
f, err := os.Open(file)
if err != nil {
c.UI.Error(fmt.Sprintf("Error opening snapshot file: %s", err))
return 1
}
defer f.Close()
var readFile *os.File
var meta *raft.SnapshotMeta
if strings.ToLower(path.Base(file)) == "state.bin" {
// This is an internal raw raft snapshot not a gzipped archive one
// downloaded from the API, we can read it directly
readFile = f
// Assume the meta is colocated and error if not.
metaRaw, err := os.ReadFile(path.Join(path.Dir(file), "meta.json"))
if err != nil {
c.UI.Error(fmt.Sprintf("Error reading meta.json from internal snapshot dir: %s", err))
return 1
}
var metaDecoded raft.SnapshotMeta
err = json.Unmarshal(metaRaw, &metaDecoded)
if err != nil {
c.UI.Error(fmt.Sprintf("Error parsing meta.json from internal snapshot dir: %s", err))
return 1
}
meta = &metaDecoded
} else {
readFile, meta, err = snapshot.Read(hclog.New(nil), f)
if err != nil {
c.UI.Error(fmt.Sprintf("Error reading snapshot: %s", err))
return 1
}
defer func() {
if err := readFile.Close(); err != nil {
c.UI.Error(fmt.Sprintf("Failed to close temp snapshot: %v", err))
}
if err := os.Remove(readFile.Name()); err != nil {
c.UI.Error(fmt.Sprintf("Failed to clean up temp snapshot: %v", err))
}
}()
}
err = c.encoder.Encode(map[string]interface{}{
"Type": "SnapshotHeader",
"Data": meta,
})
if err != nil {
c.UI.Error(fmt.Sprintf("Error encoding snapshot header to the output stream: %v", err))
return 1
}
err = c.decodeStream(readFile)
if err != nil {
c.UI.Error(fmt.Sprintf("Error extracting snapshot data: %s", err))
return 1
}
return 0
}
// enhance utilizes ReadSnapshot to populate the struct with
// all of the snapshot's itemized data
func (c *cmd) decodeStream(file io.Reader) error {
handler := func(header *fsm.SnapshotHeader, msg structs.MessageType, dec *codec.Decoder) error {
name := structs.MessageType.String(msg)
var val interface{}
if zeroVal, ok := requestTypeZeroValues[msg]; ok {
val = zeroVal()
}
err := dec.Decode(&val)
if err != nil {
return fmt.Errorf("failed to decode msg type %v, error %v", name, err)
}
err = c.encoder.Encode(map[string]interface{}{
"Type": name,
"Data": val,
})
if err != nil {
return fmt.Errorf("failed to encode data into the object stream: %w", err)
}
return nil
}
return fsm.ReadSnapshot(file, handler)
}
func (c *cmd) Synopsis() string {
return synopsis
}
func (c *cmd) Help() string {
return c.help
}
const synopsis = "Decodes the binary"
const help = `
Usage: consul snapshot decode [options] FILE
Decodes snapshot data and outputs a stream of line delimited JSON objects of the form:
{"Type": "SnapshotHeader", "Data": {"<json encoded snapshot header>"}}
{"Type": "<type name>","Data": {<json encoded data>}}
{"Type": "<type name>","Data": {<json encoded data>}}
...
`

View File

@ -0,0 +1,107 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package decode
import (
"strings"
"testing"
"github.com/hashicorp/consul/internal/testing/golden"
"github.com/hashicorp/consul/version/versiontest"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/require"
)
func TestSnapshotDecodeCommand_noTabs(t *testing.T) {
if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
t.Fatal("help has tabs")
}
}
func TestSnapshotDecodeCommand_Validation(t *testing.T) {
ui := cli.NewMockUi()
c := New(ui)
cases := map[string]struct {
args []string
output string
}{
"no file": {
[]string{},
"Missing FILE argument",
},
"extra args": {
[]string{"foo", "bar", "baz"},
"Too many arguments",
},
}
for name, tc := range cases {
// Ensure our buffer is always clear
if ui.ErrorWriter != nil {
ui.ErrorWriter.Reset()
}
if ui.OutputWriter != nil {
ui.OutputWriter.Reset()
}
code := c.Run(tc.args)
if code == 0 {
t.Errorf("%s: expected non-zero exit", name)
}
output := ui.ErrorWriter.String()
if !strings.Contains(output, tc.output) {
t.Errorf("%s: expected %q to contain %q", name, output, tc.output)
}
}
}
func TestSnapshotDecodeCommand(t *testing.T) {
cases := map[string]string{
"no-kv": "./testdata/backup.snap",
"with-kv": "./testdata/backupWithKV.snap",
"all": "./testdata/all.snap",
}
for name, fpath := range cases {
fpath := fpath
t.Run(name, func(t *testing.T) {
// Inspect the snapshot
ui := cli.NewMockUi()
c := New(ui)
args := []string{fpath}
code := c.Run(args)
if code != 0 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
actual := ui.OutputWriter.String()
fname := t.Name() + ".ce.golden"
if versiontest.IsEnterprise() {
fname = t.Name() + ".ent.golden"
}
want := golden.Get(t, actual, fname)
require.Equal(t, want, actual)
})
}
}
func TestSnapshotDecodeInvalidFile(t *testing.T) {
// Attempt to open a non-snapshot file.
filepath := "./testdata/TestSnapshotDecodeCommand/no-kv.golden"
// Inspect the snapshot
ui := cli.NewMockUi()
c := New(ui)
args := []string{filepath}
code := c.Run(args)
// Just check it was an error code returned and not a panic - originally this
// would panic.
if code == 0 {
t.Fatalf("should return an error code")
}
}

View File

@ -0,0 +1,110 @@
{"Data":{"Version":1,"ID":"2-62-1710350056693","Index":62,"Term":2,"Peers":"ka4xMjcuMC4wLjE6ODMwMA==","Configuration":{"Servers":[{"Suffrage":0,"ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Address":"127.0.0.1:8300"}]},"ConfigurationIndex":1,"Size":25469},"Type":"SnapshotHeader"}
{"Data":"\n\u0007default\u0012\u0019Builtin Default Namespace0\n8\n","Type":"Unknown(65)"}
{"Data":"\n\u0007default\u0012\u0019Builtin Default Partition \t(\t","Type":"Unknown(69)"}
{"Data":{"Service":{"ServiceName":{"Name":"external"},"Peer":""},"IP":"0.0.0.3","ManualIPs":null,"CreateIndex":43,"ModifyIndex":43},"Type":"ServiceVirtualIP"}
{"Data":{"Service":{"ServiceName":{"Name":"foo"},"Peer":""},"IP":"0.0.0.2","ManualIPs":null,"CreateIndex":38,"ModifyIndex":38},"Type":"ServiceVirtualIP"}
{"Data":{"Service":{"ServiceName":{"Name":"web"},"Peer":""},"IP":"0.0.0.1","ManualIPs":null,"CreateIndex":37,"ModifyIndex":37},"Type":"ServiceVirtualIP"}
{"Data":{"IP":"0.0.0.3","IsCounter":true},"Type":"FreeVirtualIP"}
{"Data":{"Datacenter":"dc1","ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Node":"mkeeler-C02F44FDMD6R","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":"","consul-version":"1.19.0"},"Service":null,"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":21,"ModifyIndex":22},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Node":"mkeeler-C02F44FDMD6R","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":"","consul-version":"1.19.0"},"Service":{"ID":"consul","Service":"consul","Tags":null,"Address":"","Meta":{"grpc_port":"8502","grpc_tls_port":"8503","non_voter":"false","raft_version":"3","read_replica":"false","serf_protocol_current":"2","serf_protocol_max":"5","serf_protocol_min":"1","version":"1.19.0"},"Port":8300,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":21,"ModifyIndex":21},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":21,"ModifyIndex":22},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Node":"mkeeler-C02F44FDMD6R","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":"","consul-version":"1.19.0"},"Service":null,"Check":{"Node":"mkeeler-C02F44FDMD6R","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"Type":"","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":21,"ModifyIndex":21},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":21,"ModifyIndex":22},"Type":"Register"}
{"Data":{"Datacenter":"","Op":"","Session":{"ID":"","Name":"","Node":"","LockDelay":0,"Behavior":"","TTL":"","NodeChecks":null,"ServiceChecks":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"Session"}
{"Data":{"AccessorID":"d56136c7-a3a8-ceac-da70-9bee9755d252","SecretID":"a4794332-5fe2-51e1-3a78-47c684bd181c","Description":"","NodeIdentities":[{"NodeName":"localhost","Datacenter":"dc1"}],"Local":false,"CreateTime":"2024-03-13T13:14:15.109823-04:00","Hash":"ibqA3nqRxdh2zAJSHY+nIphdDX/hpYOmgv3RASkkU1w=","CreateIndex":31,"ModifyIndex":31},"Type":"ACLToken"}
{"Data":{"AccessorID":"00000000-0000-0000-0000-000000000002","SecretID":"anonymous","Description":"Anonymous Token","Local":false,"CreateTime":"2024-03-13T13:14:09.953116-04:00","Hash":"tgCOyeidw+oaoZXQ9mHy6+EnY7atKoGaBzg2ndTwXl0=","CreateIndex":7,"ModifyIndex":7},"Type":"ACLToken"}
{"Data":{"AccessorID":"cbb26776-68df-d4ec-5b38-b40366ebf6c2","SecretID":"root","Description":"Initial Management Token","Policies":[{"ID":"00000000-0000-0000-0000-000000000001","Name":"global-management"}],"Local":false,"CreateTime":"2024-03-13T13:14:09.951135-04:00","Hash":"a5y709jeB8xI19PvumK2BeZG3u+1w3hfzyxf2s3UdDY=","CreateIndex":6,"ModifyIndex":6},"Type":"ACLToken"}
{"Data":{"ID":"00000000-0000-0000-0000-000000000001","Name":"global-management","Description":"A built-in policy that grants read and write access to all Consul features","Rules":"\nacl = \"write\"\nagent_prefix \"\" {\n\tpolicy = \"write\"\n}\nevent_prefix \"\" {\n\tpolicy = \"write\"\n}\nidentity_prefix \"\" {\n\tpolicy = \"write\"\n\tintentions = \"write\"\n}\nkey_prefix \"\" {\n\tpolicy = \"write\"\n}\nkeyring = \"write\"\nnode_prefix \"\" {\n\tpolicy = \"write\"\n}\noperator = \"write\"\nmesh = \"write\"\npeering = \"write\"\nquery_prefix \"\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"write\"\n\tintentions = \"write\"\n}\nsession_prefix \"\" {\n\tpolicy = \"write\"\n}\npartition_prefix \"\" {\n\tmesh = \"write\"\n\tpeering = \"write\"\n\tnamespace \"default\" {\n\t\tnode_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t\tagent_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t}\n\tnamespace_prefix \"\" {\n\t\tacl = \"write\"\n\t\tidentity_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t\tintentions = \"write\"\n\t\t}\n\t\tkey_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t\tnode_prefix \"\" {\n\t\t\t# node policy is restricted to read within a namespace\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tsession_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t\tservice_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t\tintentions = \"write\"\n\t\t}\n\t}\n}\n","Hash":"NXp0drmQNPohGVdZ4mkRoOqe6Vtx2wYMuXHvQJNMbiE=","CreateIndex":4,"ModifyIndex":4},"Type":"ACLPolicy"}
{"Data":{"ID":"00000000-0000-0000-0000-000000000002","Name":"builtin/global-read-only","Description":"A built-in policy that grants read-only access to all Consul features","Rules":"\nacl = \"read\"\nagent_prefix \"\" {\n\tpolicy = \"read\"\n}\nevent_prefix \"\" {\n\tpolicy = \"read\"\n}\nidentity_prefix \"\" {\n\tpolicy = \"read\"\n\tintentions = \"read\"\n}\nkey_prefix \"\" {\n\tpolicy = \"read\"\n}\nkeyring = \"read\"\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\noperator = \"read\"\nmesh = \"read\"\npeering = \"read\"\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n\tintentions = \"read\"\n}\nsession_prefix \"\" {\n\tpolicy = \"read\"\n}\npartition_prefix \"\" {\n\tmesh = \"read\"\n\tpeering = \"read\"\n\tnamespace \"default\" {\n\t\tnode_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tagent_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t}\n\tnamespace_prefix \"\" {\n\t\tacl = \"read\"\n\t\tidentity_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t\tintentions = \"read\"\n\t\t}\n\t\tkey_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tnode_prefix \"\" {\n\t\t\t# node policy is restricted to read within a namespace\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tsession_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tservice_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t\tintentions = \"read\"\n\t\t}\n\t}\n}\n","Hash":"l1CO3kg8k1ikfGq3P309ZHfazlibtJ9RSGfDminehaE=","CreateIndex":5,"ModifyIndex":5},"Type":"ACLPolicy"}
{"Data":{"ID":"cefa650e-8538-974a-00a0-833c6aa4634a","Name":"test","Description":"","Rules":"node_prefix \"\" { policy = \"write\" }","Hash":"Utaz0IM7r4OLGrVW3ESeiZVGaaql+03cjTU7UHZiVJs=","CreateIndex":32,"ModifyIndex":32},"Type":"ACLPolicy"}
{"Data":{"ID":"edbab2c0-4bd2-052f-8a08-2f31e65930b2","Name":"test","Description":"","Policies":[{"ID":"cefa650e-8538-974a-00a0-833c6aa4634a","Name":"test"}],"Hash":"lfkCqRLtTKoFk50xI5Hxij13bfzsyg7IN7kYwnMP4Y0=","CreateIndex":33,"ModifyIndex":33},"Type":"ACLRole"}
{"Data":{"ID":"2a7708b7-913a-8c1f-593f-019c7192d549","Description":"","AuthMethod":"test","Selector":"","BindType":"service","BindName":"service","CreateIndex":35,"ModifyIndex":35},"Type":"ACLBindingRule"}
{"Data":{"Name":"test","Type":"jwt","Config":{"JWTValidationPubKeys":["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENRw6ZwlBOx5XZKjcc1HhU00sDehc\n8nqeeSnRZLv89yT7M7qUOFDtR29FR/AFUSAEOFl1iIYLqNMElHs2VkgAZA==\n-----END PUBLIC KEY-----"]},"CreateIndex":34,"ModifyIndex":34},"Type":"ACLAuthMethod"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","ReapIndex":0,"Token":""},"Type":"Tombstone"}
{"Data":{"Datacenter":"","Op":"","Query":null,"Token":"root"},"Type":"PreparedQuery"}
{"Data":{"Datacenter":"","Config":{"CleanupDeadServers":false,"LastContactThreshold":0,"MaxTrailingLogs":0,"MinQuorum":0,"ServerStabilizationTime":0,"RedundancyZoneTag":"","DisableUpgradeMigration":false,"UpgradeVersionTag":"","CreateIndex":0,"ModifyIndex":0},"CAS":false,"Token":""},"Type":"Autopilot"}
{"Data":{"Op":"","Datacenter":"","Index":0,"Roots":null,"Config":null,"ProviderState":null,"Token":""},"Type":"ConnectCA"}
{"Data":{"ID":"fb:50:9b:45:1a:65:15:c1:68:57:73:5f:da:cd:b8:0d:0f:e2:26:eb:68:66:43:11:85:9d:67:a9:7a:56:9c:b9","PrivateKey":"-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMnCtDuifZocILamO9VdbQtXoY6SGSDVknyV+HwbRRzUoAoGCCqGSM49\nAwEHoUQDQgAEf0yW1ejMmToqCbhtSPvlXylSnS8bxJtJD6fs4VGYh7567DjGfBda\nEdgefebLuDdPPl9xAzNOihV29jSb6WheUQ==\n-----END EC PRIVATE KEY-----\n","RootCert":"-----BEGIN CERTIFICATE-----\nMIICDjCCAbOgAwIBAgIBDjAKBggqhkjOPQQDAjAwMS4wLAYDVQQDEyVwcmktZ2Fn\nMXhrYS5jb25zdWwuY2EuZmM2YmY5NDYuY29uc3VsMB4XDTI0MDMxMzE3MTQwOVoX\nDTM0MDMxMTE3MTQwOVowMDEuMCwGA1UEAxMlcHJpLWdhZzF4a2EuY29uc3VsLmNh\nLmZjNmJmOTQ2LmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH9MltXo\nzJk6Kgm4bUj75V8pUp0vG8SbSQ+n7OFRmIe+euw4xnwXWhHYHn3my7g3Tz5fcQMz\nTooVdvY0m+loXlGjgb0wgbowDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB\nAf8wKQYDVR0OBCIEILHtYgr0Zfai/xwJ6PEXOiNAtlDhn3ZSRkZcQNCGq+RnMCsG\nA1UdIwQkMCKAILHtYgr0Zfai/xwJ6PEXOiNAtlDhn3ZSRkZcQNCGq+RnMD8GA1Ud\nEQQ4MDaGNHNwaWZmZTovL2ZjNmJmOTQ2LTk3MzgtMzNmMi1hYmI2LThlYWI2ZGU1\nNmZiYS5jb25zdWwwCgYIKoZIzj0EAwIDSQAwRgIhAL/pd0eKuR/DoWBCYBV2ATNO\nPXjoamqziYct83HMqfv+AiEAzys8TxOmt6h83TujE+2CFmZxRZ1wTdUHPC4efjOb\nahw=\n-----END CERTIFICATE-----\n","IntermediateCert":"","CreateIndex":13,"ModifyIndex":15},"Type":"ConnectCAProviderState"}
{"Data":{"Provider":"consul","Config":{"IntermediateCertTTL":"8760h","LeafCertTTL":"72h","RootCertTTL":"87600h"},"State":null,"ForceWithoutCrossSigning":false,"CreateIndex":12,"ModifyIndex":16},"Type":"ConnectCAConfig"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"api-gateway","Name":"apigw","Listeners":[{"Name":"tcp","Hostname":"","Port":443,"Protocol":"tcp","TLS":{"Certificates":[{"Kind":"inline-certificate","Name":"blah","SectionName":""}],"MaxVersion":"","MinVersion":"","CipherSuites":null}},{"Name":"http","Hostname":"","Port":8080,"Protocol":"http","TLS":{"Certificates":null,"MaxVersion":"","MinVersion":"","CipherSuites":null}}],"Status":{"Conditions":[{"Type":"Accepted","Status":"True","Reason":"Accepted","Message":"gateway is valid","Resource":{"Kind":"","Name":"","SectionName":""},"LastTransitionTime":"2024-03-13T17:14:16.170758Z"},{"Type":"Conflicted","Status":"False","Reason":"NoConflict","Message":"listener has no route conflicts","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"http"},"LastTransitionTime":"2024-03-13T17:14:16.170763Z"},{"Type":"Conflicted","Status":"False","Reason":"NoConflict","Message":"listener has no route conflicts","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"},"LastTransitionTime":"2024-03-13T17:14:16.170763Z"},{"Type":"ResolvedRefs","Status":"True","Reason":"ResolvedRefs","Message":"resolved refs","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"http"},"LastTransitionTime":"2024-03-13T17:14:16.170756Z"},{"Type":"ResolvedRefs","Status":"True","Reason":"ResolvedRefs","Message":"resolved refs","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"},"LastTransitionTime":"2024-03-13T17:14:16.170757Z"}]},"Hash":6495004227697965289,"CreateIndex":48,"ModifyIndex":49},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"bound-api-gateway","Name":"apigw","Listeners":[{"Name":"tcp","Routes":[{"Kind":"tcp-route","Name":"fake","SectionName":""}],"Certificates":[{"Kind":"inline-certificate","Name":"blah","SectionName":""}]},{"Name":"http","Routes":null,"Certificates":null}],"Services":{"fake":[{"Kind":"tcp-route","Name":"fake","SectionName":""}]},"CreateIndex":50,"ModifyIndex":55},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"exported-services","Name":"default","Services":[{"Name":"web","Namespace":"default","Consumers":[{"Peer":"other"}]}],"Hash":15272881108129132528,"CreateIndex":46,"ModifyIndex":46},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"http-route","Name":"web","Parents":[{"Kind":"api-gateway","Name":"apigw","SectionName":"http"}],"Rules":[{"Filters":{"Headers":null,"URLRewrite":null,"RetryFilter":null,"TimeoutFilter":null,"JWT":null},"ResponseFilters":{"Headers":null},"Matches":null,"Services":[{"Name":"fake","Weight":1,"Filters":{"Headers":null,"URLRewrite":null,"RetryFilter":null,"TimeoutFilter":null,"JWT":null},"ResponseFilters":{"Headers":null}}]}],"Hostnames":null,"Status":{"Conditions":[{"Type":"Accepted","Status":"False","Reason":"InvalidDiscoveryChain","Message":"route protocol does not match targeted service protocol","Resource":{"Kind":"","Name":"","SectionName":""},"LastTransitionTime":"2024-03-13T17:14:16.417825Z"},{"Type":"Bound","Status":"False","Reason":"FailedToBind","Message":"failed to bind route to gateway apigw: route has not been accepted","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"http"},"LastTransitionTime":"2024-03-13T17:14:16.417832Z"}]},"Hash":1173445267586960895,"CreateIndex":56,"ModifyIndex":57},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"ingress-gateway","Name":"api","TLS":{"Enabled":false},"Listeners":null,"Hash":15966540600821199974,"CreateIndex":42,"ModifyIndex":42},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"inline-certificate","Name":"blah","Certificate":"-----BEGIN CERTIFICATE-----\nMIICnjCCAkSgAwIBAgIQAxVHhSG0wSbdZm+3ToYAkDAKBggqhkjOPQQDAjCBuTEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMUAwPgYDVQQDEzdDb25zdWwgQWdlbnQgQ0Eg\nMjgwNzE4MDMxODA1Mjk2OTA1NzQ4MzU3NjI1MTI5ODQ5NDA5NjI3MCAXDTIzMTEw\nMjE1Mjk0NVoYDzIxMjMxMDA5MTUyOTQ1WjAcMRowGAYDVQQDExFjbGllbnQuZGMx\nLmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKvl1yhbsI9r7IxJxLrt\nZTNYXkCXuFy8q3gsokMqsl/MUynrIBrd9NrZEQA91ZArUYzF1+QlxM6D4hRJc5CR\n3x6jgccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr\nBgEFBQcDATAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCCvXve+zMFSJMXNS3l3YL9k\n2QH8zF74wa+TlwFSaQEjGzArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++x\nHG8dRBUpwvSk0Mk1+jAtBgNVHREEJjAkghFjbGllbnQuZGMxLmNvbnN1bIIJbG9j\nYWxob3N0hwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIBLqa1Zh3KUE0RiQzWdoYXkU\nwZo5aBw9ujqzLyAqxToFAiEAihWmc4r6lDYRR35X4QB1nTT92POJRClsfLPOTRG5\nrsU=\n-----END CERTIFICATE-----","PrivateKey":"-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINE2CQhnu7ipo67FGbEBRXoYRCTM4uJdHgNRTrdkAnHCoAoGCCqGSM49\nAwEHoUQDQgAEq+XXKFuwj2vsjEnEuu1lM1heQJe4XLyreCyiQyqyX8xTKesgGt30\n2tkRAD3VkCtRjMXX5CXEzoPiFElzkJHfHg==\n-----END EC PRIVATE KEY-----","Hash":3420847368935414704,"CreateIndex":47,"ModifyIndex":47},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"jwt-provider","Name":"whocare","JSONWebKeySet":{"Local":{"Filename":"/tmp/jwks.json"}},"ClockSkewSeconds":30,"Hash":11700458008192259302,"CreateIndex":58,"ModifyIndex":58},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"mesh","TransparentProxy":{"MeshDestinationsOnly":false},"AllowEnablingPermissiveMutualTLS":true,"Hash":10541910966466195416,"CreateIndex":45,"ModifyIndex":45},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"proxy-defaults","Name":"global","Config":null,"TransparentProxy":{},"MeshGateway":{},"Expose":{},"AccessLogs":{},"Hash":2982631359577466273,"CreateIndex":36,"ModifyIndex":36},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"sameness-group","Name":"default","DefaultForFailover":true,"IncludeLocal":true,"Members":[{"Peer":"other"}],"Hash":8697701191886031964,"CreateIndex":51,"ModifyIndex":51},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-defaults","Name":"foo","Protocol":"http","TransparentProxy":{},"MeshGateway":{},"Expose":{},"Hash":6851507846005072818,"CreateIndex":38,"ModifyIndex":38},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-defaults","Name":"web","Protocol":"http","TransparentProxy":{},"MeshGateway":{},"Expose":{},"Hash":7641900064431671148,"CreateIndex":37,"ModifyIndex":37},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-intentions","Name":"web","Sources":[{"Name":"api","Action":"allow","Precedence":9,"Type":"consul"}],"Hash":1271129721167983805,"CreateIndex":44,"ModifyIndex":44},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"RequestTimeout":"3s","Kind":"service-resolver","Name":"web","Hash":3307964110661939386,"CreateIndex":41,"ModifyIndex":41},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-router","Name":"foo","Routes":[{"Match":{"HTTP":{"PathPrefix":"/foo"}},"Destination":{"Service":"web","Namespace":"default","Partition":"default"}}],"Hash":101247989479106989,"CreateIndex":39,"ModifyIndex":39},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-splitter","Name":"web","Splits":[{"Weight":100,"Service":"web"}],"Hash":18208480688038965425,"CreateIndex":40,"ModifyIndex":40},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"tcp-route","Name":"fake","Parents":[{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"}],"Services":[{"Name":"fake"}],"Status":{"Conditions":[{"Type":"Accepted","Status":"True","Reason":"Accepted","Message":"route is valid","Resource":{"Kind":"","Name":"","SectionName":""},"LastTransitionTime":"2024-03-13T17:14:16.353589Z"},{"Type":"Bound","Status":"True","Reason":"Bound","Message":"successfully bound route","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"},"LastTransitionTime":"2024-03-13T17:14:16.353602Z"}]},"Hash":4006422401340817930,"CreateIndex":52,"ModifyIndex":54},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"terminating-gateway","Name":"external","Services":[{"Name":"external"}],"Hash":15903386135938294095,"CreateIndex":43,"ModifyIndex":43},"Token":""},"Type":"ConfigEntry"}
{"Data":{"Datacenter":"","Op":"upsert","State":{"Datacenter":"dc1","UpdatedAt":"2024-03-13T17:14:10.392908Z","PrimaryModifyIndex":23,"CreateIndex":23,"ModifyIndex":23},"Token":""},"Type":"FederationState"}
{"Data":{"Key":"intention-format","Value":"config-entry","CreateIndex":17,"ModifyIndex":17},"Type":"SystemMetadata"}
{"Data":{"Key":"reporting-process-id","Value":"01HRWCX8N4S6GEPX7EMTK17B6F","CreateIndex":20,"ModifyIndex":20},"Type":"SystemMetadata"}
{"Data":{"Key":"server-management-token","Value":"16ccea12-b43d-eb04-d1f6-205124572d70","CreateIndex":8,"ModifyIndex":8},"Type":"SystemMetadata"}
{"Data":{"Key":"virtual-ips","Value":"true","CreateIndex":18,"ModifyIndex":18},"Type":"SystemMetadata"}
{"Data":{"Key":"virtual-ips-term-gateway","Value":"true","CreateIndex":19,"ModifyIndex":19},"Type":"SystemMetadata"}
{"Data":{"Key":"acl-auth-methods","Value":34},"Type":"Index"}
{"Data":{"Key":"acl-binding-rules","Value":35},"Type":"Index"}
{"Data":{"Key":"acl-policies","Value":32},"Type":"Index"}
{"Data":{"Key":"acl-roles","Value":33},"Type":"Index"}
{"Data":{"Key":"acl-token-bootstrap","Value":6},"Type":"Index"}
{"Data":{"Key":"acl-tokens","Value":31},"Type":"Index"}
{"Data":{"Key":"checks","Value":21},"Type":"Index"}
{"Data":{"Key":"config-entries","Value":58},"Type":"Index"}
{"Data":{"Key":"connect-ca-builtin","Value":15},"Type":"Index"}
{"Data":{"Key":"connect-ca-builtin-serial","Value":15},"Type":"Index"}
{"Data":{"Key":"connect-ca-roots","Value":16},"Type":"Index"}
{"Data":{"Key":"connect-intentions","Value":17},"Type":"Index"}
{"Data":{"Key":"federation-states","Value":23},"Type":"Index"}
{"Data":{"Key":"gateway-services","Value":43},"Type":"Index"}
{"Data":{"Key":"kind_service_names.partition.default:namespace.default:typical","Value":21},"Type":"Index"}
{"Data":{"Key":"kind_service_names.partition.default:typical","Value":21},"Type":"Index"}
{"Data":{"Key":"kind_service_names.typical","Value":21},"Type":"Index"}
{"Data":{"Key":"mesh-topology","Value":42},"Type":"Index"}
{"Data":{"Key":"nodes","Value":22},"Type":"Index"}
{"Data":{"Key":"partition","Value":9},"Type":"Index"}
{"Data":{"Key":"partition.default:acl-auth-methods","Value":34},"Type":"Index"}
{"Data":{"Key":"partition.default:acl-binding-rules","Value":35},"Type":"Index"}
{"Data":{"Key":"partition.default:acl-policies","Value":32},"Type":"Index"}
{"Data":{"Key":"partition.default:acl-roles","Value":33},"Type":"Index"}
{"Data":{"Key":"partition.default:acl-tokens","Value":31},"Type":"Index"}
{"Data":{"Key":"partition.default:kvs","Value":28},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace","Value":10},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:acl-auth-methods","Value":34},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:acl-binding-rules","Value":35},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:acl-policies","Value":32},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:acl-roles","Value":33},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:acl-tokens","Value":31},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:kvs","Value":28},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:sessions","Value":29},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:tombstones","Value":28},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:checks","Value":21},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:namespace.default:checks","Value":21},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:namespace.default:service.consul","Value":22},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:namespace.default:service_kind.typical","Value":22},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:namespace.default:services","Value":21},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:node.mkeeler-C02F44FDMD6R","Value":22},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:nodes","Value":22},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:service_kind.typical","Value":22},"Type":"Index"}
{"Data":{"Key":"partition.default:peer.~:services","Value":21},"Type":"Index"}
{"Data":{"Key":"partition.default:peering","Value":62},"Type":"Index"}
{"Data":{"Key":"partition.default:peering-trust-bundles","Value":62},"Type":"Index"}
{"Data":{"Key":"partition.default:service-virtual-ips","Value":43},"Type":"Index"}
{"Data":{"Key":"partition.default:sessions","Value":29},"Type":"Index"}
{"Data":{"Key":"partition.default:namespace.default:tombstones","Value":28},"Type":"Index"}
{"Data":{"Key":"peering","Value":62},"Type":"Index"}
{"Data":{"Key":"peering-trust-bundles","Value":62},"Type":"Index"}
{"Data":{"Key":"prepared-queries","Value":30},"Type":"Index"}
{"Data":{"Key":"services","Value":21},"Type":"Index"}
{"Data":{"Key":"sessions","Value":29},"Type":"Index"}
{"Data":{"Key":"system-metadata","Value":20},"Type":"Index"}
{"Data":{"ID":"503f605c-6ac3-1bbc-4518-758e07212491","Name":"other","Partition":"default","State":1,"PeerCAPems":["-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIBCTAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktMWhk\nZG90d2IuY29uc3VsLmNhLjU4NGVjZjgyLmNvbnN1bDAeFw0yNDAzMTMxNzE0MDla\nFw0zNDAzMTExNzE0MDlaMDExLzAtBgNVBAMTJnByaS0xaGRkb3R3Yi5jb25zdWwu\nY2EuNTg0ZWNmODIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFC3D\n0+YDsc7BhFLJy5ePs5W86pEGScYI0PWilubR+NrV4o40hqgTbwANieTjd77oQTYr\nXD+uaPj+pIOnuOu5LqOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMw\nKwYDVR0jBCQwIoAgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vNTg0ZWNmODItZmU5YS00NDY0LTVkZWItMjU5ZTRh\nYmExZGVlLmNvbnN1bDAKBggqhkjOPQQDAgNIADBFAiEAzD28+wMMO3RPfYR4kF9G\ncrqWkBCWP7k2fvwX10vLdNwCIBKf0pWS1qTOgJDxX1dn9+vqk1flv7stwwgFgJlH\nT0xb\n-----END CERTIFICATE-----\n"],"CreateIndex":59,"ModifyIndex":62,"Remote":{"Partition":"default","Datacenter":"dc1"}},"Type":"Peering"}
{"Data":{"TrustDomain":"584ecf82-fe9a-4464-5deb-259e4aba1dee.consul","PeerName":"other","Partition":"default","RootPEMs":["-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIBCTAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktMWhk\nZG90d2IuY29uc3VsLmNhLjU4NGVjZjgyLmNvbnN1bDAeFw0yNDAzMTMxNzE0MDla\nFw0zNDAzMTExNzE0MDlaMDExLzAtBgNVBAMTJnByaS0xaGRkb3R3Yi5jb25zdWwu\nY2EuNTg0ZWNmODIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFC3D\n0+YDsc7BhFLJy5ePs5W86pEGScYI0PWilubR+NrV4o40hqgTbwANieTjd77oQTYr\nXD+uaPj+pIOnuOu5LqOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMw\nKwYDVR0jBCQwIoAgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vNTg0ZWNmODItZmU5YS00NDY0LTVkZWItMjU5ZTRh\nYmExZGVlLmNvbnN1bDAKBggqhkjOPQQDAgNIADBFAiEAzD28+wMMO3RPfYR4kF9G\ncrqWkBCWP7k2fvwX10vLdNwCIBKf0pWS1qTOgJDxX1dn9+vqk1flv7stwwgFgJlH\nT0xb\n-----END CERTIFICATE-----\n"],"ExportedPartition":"default","CreateIndex":62,"ModifyIndex":62},"Type":"PeeringTrustBundle"}
{"Data":{"PeerID":"503f605c-6ac3-1bbc-4518-758e07212491","stream":{"ActiveSecretID":"cda5e0b8-be51-5b62-a89d-8546f9c48da9"}},"Type":"PeeringSecret"}
{"Data":{"ChunkMap":{}},"Type":"ChunkingState"}

View File

@ -0,0 +1,23 @@
{"Data":{"Version":1,"ID":"2-13-1602222343947","Index":13,"Term":2,"Peers":"ka4xMjcuMC4wLjE6ODMwMA==","Configuration":{"Servers":[{"Suffrage":0,"ID":"a577b288-b354-770e-e909-da0972eb20e8","Address":"127.0.0.1:8300"}]},"ConfigurationIndex":1,"Size":5141},"Type":"SnapshotHeader"}
{"Data":{"Datacenter":"dc1","ID":"a577b288-b354-770e-e909-da0972eb20e8","Node":"macbook-pro.lan","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":11,"ModifyIndex":12},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"a577b288-b354-770e-e909-da0972eb20e8","Node":"macbook-pro.lan","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":""},"Service":{"ID":"consul","Service":"consul","Tags":null,"Address":"","Meta":{"non_voter":"false","raft_version":"3","serf_protocol_current":"2","serf_protocol_max":"5","serf_protocol_min":"1","version":"1.9.0"},"Port":8300,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":11,"ModifyIndex":11},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":11,"ModifyIndex":12},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"a577b288-b354-770e-e909-da0972eb20e8","Node":"macbook-pro.lan","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":{"Node":"macbook-pro.lan","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"Type":"","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":11,"ModifyIndex":11},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":11,"ModifyIndex":12},"Type":"Register"}
{"Data":{"Datacenter":"","Config":{"CleanupDeadServers":false,"LastContactThreshold":0,"MaxTrailingLogs":0,"MinQuorum":0,"ServerStabilizationTime":0,"RedundancyZoneTag":"","DisableUpgradeMigration":false,"UpgradeVersionTag":"","CreateIndex":0,"ModifyIndex":0},"CAS":false,"Token":""},"Type":"Autopilot"}
{"Data":{"Op":"","Datacenter":"","Index":0,"Roots":null,"Config":null,"ProviderState":null,"Token":""},"Type":"ConnectCA"}
{"Data":{"ID":"07:80:c8:de:f6:41:86:29:8f:9c:b8:17:d6:48:c2:d5:c5:5c:7f:0c:03:f7:cf:97:5a:a7:c1:68:aa:23:ae:81","PrivateKey":"-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIGwMuojUj9fSERmBjUjp3AbmkFhwRZZEEcm0XgdnCSyRoAoGCCqGSM49\nAwEHoUQDQgAEBi0AvynqnFMRIsxs1VNKkDBIvlKywpuFIaZY3TDMEvuVV/iLvFOl\n8I/OBkjXVsUPzXpao6Da6oPpbtzVuphD7A==\n-----END EC PRIVATE KEY-----\n","RootCert":"-----BEGIN CERTIFICATE-----\nMIICDjCCAbOgAwIBAgIBBzAKBggqhkjOPQQDAjAwMS4wLAYDVQQDEyVwcmktMXN5\nYzU4Zi5jb25zdWwuY2EuMzMzZDFmYTIuY29uc3VsMB4XDTIwMTAwOTA1NDUyNloX\nDTMwMTAwOTA1NDUyNlowMDEuMCwGA1UEAxMlcHJpLTFzeWM1OGYuY29uc3VsLmNh\nLjMzM2QxZmEyLmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAYtAL8p\n6pxTESLMbNVTSpAwSL5SssKbhSGmWN0wzBL7lVf4i7xTpfCPzgZI11bFD816WqOg\n2uqD6W7c1bqYQ+yjgb0wgbowDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB\nAf8wKQYDVR0OBCIEIOZNpB8CrBdX2haue5rcSaauDsPs8S1Ld39j9ne1JP+xMCsG\nA1UdIwQkMCKAIOZNpB8CrBdX2haue5rcSaauDsPs8S1Ld39j9ne1JP+xMD8GA1Ud\nEQQ4MDaGNHNwaWZmZTovLzMzM2QxZmEyLTFjMTItMzgzYS05MDRlLWFmMjc0OTEz\nNmViZS5jb25zdWwwCgYIKoZIzj0EAwIDSQAwRgIhALy+D4SiHnHaEtxj62ncLyus\nxf6XS4amT2P3uc+zsURWAiEAvGAvh5/BwyUg0wzcVGZ40K+tllAVmk4fWL6dkUcT\nJ+o=\n-----END CERTIFICATE-----\n","IntermediateCert":"","CreateIndex":6,"ModifyIndex":8},"Type":"ConnectCAProviderState"}
{"Data":{"Provider":"consul","Config":{"IntermediateCertTTL":"8760h","LeafCertTTL":"72h","RotationPeriod":"2160h"},"State":null,"ForceWithoutCrossSigning":false,"CreateIndex":5,"ModifyIndex":5},"Type":"ConnectCAConfig"}
{"Data":{"Datacenter":"","Op":"upsert","State":{"Datacenter":"dc1","UpdatedAt":"2020-10-09T05:45:26.48447Z","PrimaryModifyIndex":13,"CreateIndex":13,"ModifyIndex":13},"Token":""},"Type":"FederationState"}
{"Data":{"Key":"intention-format","Value":"config-entry","CreateIndex":10,"ModifyIndex":10},"Type":"SystemMetadata"}
{"Data":{"Key":"checks","Value":11},"Type":"Index"}
{"Data":{"Key":"config-entries","Value":10},"Type":"Index"}
{"Data":{"Key":"connect-ca-builtin","Value":8},"Type":"Index"}
{"Data":{"Key":"connect-ca-builtin-serial","Value":7},"Type":"Index"}
{"Data":{"Key":"connect-ca-roots","Value":9},"Type":"Index"}
{"Data":{"Key":"connect-intentions","Value":10},"Type":"Index"}
{"Data":{"Key":"federation-states","Value":13},"Type":"Index"}
{"Data":{"Key":"nodes","Value":12},"Type":"Index"}
{"Data":{"Key":"service.consul","Value":12},"Type":"Index"}
{"Data":{"Key":"service_kind.typical","Value":12},"Type":"Index"}
{"Data":{"Key":"services","Value":11},"Type":"Index"}
{"Data":{"Key":"system-metadata","Value":10},"Type":"Index"}
{"Data":{"ChunkMap":{}},"Type":"ChunkingState"}

View File

@ -0,0 +1,51 @@
{"Data":{"Version":1,"ID":"2-12426-1604593650375","Index":12426,"Term":2,"Peers":"kbMxOTIuMTY4Ljg2LjIzNjo4MzAw","Configuration":{"Servers":[{"Suffrage":0,"ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Address":"192.168.86.236:8300"}]},"ConfigurationIndex":1,"Size":17228},"Type":"SnapshotHeader"}
{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":{"ID":"consul","Service":"consul","Tags":null,"Address":"","Meta":{"non_voter":"false","raft_version":"3","serf_protocol_current":"2","serf_protocol_max":"5","serf_protocol_min":"1","version":"1.8.5"},"Port":8300,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":6,"ModifyIndex":6},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":{"ID":"vault:127.0.0.1:8200","Service":"vault","Tags":["active","initialized"],"Address":"127.0.0.1","TaggedAddresses":{"lan_ipv4":{"Address":"127.0.0.1","Port":8200},"wan_ipv4":{"Address":"127.0.0.1","Port":8200}},"Meta":null,"Port":8200,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":3470,"ModifyIndex":3497},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":{"Node":"hashicorp.lan","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"Type":"","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":6,"ModifyIndex":6},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"}
{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":{"Node":"hashicorp.lan","CheckID":"vault:127.0.0.1:8200:vault-sealed-check","Name":"Vault Sealed Status","Status":"passing","Notes":"Vault service is healthy when Vault is in an unsealed status and can become an active Vault server","Output":"Vault Unsealed","ServiceID":"vault:127.0.0.1:8200","ServiceName":"vault","ServiceTags":["active","initialized"],"Type":"ttl","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":3471,"ModifyIndex":6836},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"}
{"Data":[{"Node":"hashicorp.lan","Segment":"","Coord":{"Vec":[0,0,0,0,0,0,0,0],"Error":1.5,"Adjustment":0,"Height":0.00001}}],"Type":"CoordinateBatchUpdate"}
{"Data":{"Datacenter":"","Op":"","Session":{"ID":"","Name":"","Node":"","LockDelay":0,"Behavior":"","TTL":"","NodeChecks":null,"ServiceChecks":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"Session"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"}
{"Data":{"Datacenter":"","Op":"","ReapIndex":0,"Token":""},"Type":"Tombstone"}
{"Data":{"Datacenter":"","Op":"","ReapIndex":0,"Token":""},"Type":"Tombstone"}
{"Data":{"Datacenter":"","Config":{"CleanupDeadServers":false,"LastContactThreshold":0,"MaxTrailingLogs":0,"MinQuorum":0,"ServerStabilizationTime":0,"RedundancyZoneTag":"","DisableUpgradeMigration":false,"UpgradeVersionTag":"","CreateIndex":0,"ModifyIndex":0},"CAS":false,"Token":""},"Type":"Autopilot"}
{"Data":{"Datacenter":"","Op":"upsert","State":{"Datacenter":"dc1","UpdatedAt":"2020-11-03T23:57:19.636962Z","PrimaryModifyIndex":5,"CreateIndex":5,"ModifyIndex":5},"Token":""},"Type":"FederationState"}
{"Data":{"Key":"checks","Value":6836},"Type":"Index"}
{"Data":{"Key":"coordinates","Value":12424},"Type":"Index"}
{"Data":{"Key":"federation-states","Value":5},"Type":"Index"}
{"Data":{"Key":"kvs","Value":12426},"Type":"Index"}
{"Data":{"Key":"nodes","Value":7},"Type":"Index"}
{"Data":{"Key":"service.consul","Value":7},"Type":"Index"}
{"Data":{"Key":"service.vault","Value":6836},"Type":"Index"}
{"Data":{"Key":"service_kind.typical","Value":6836},"Type":"Index"}
{"Data":{"Key":"services","Value":3497},"Type":"Index"}
{"Data":{"Key":"sessions","Value":3493},"Type":"Index"}
{"Data":{"Key":"tombstones","Value":12426},"Type":"Index"}
{"Data":{"ChunkMap":{}},"Type":"ChunkingState"}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,296 @@
#!/bin/bash
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
set -e
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
readonly SCRIPT_DIR="$(dirname ${BASH_SOURCE[0]})"
# Start a couple dev agents in the background
echo "Starting Dev Agents"
consul agent -dev -hcl 'acl { enabled = true default_policy="allow" tokens { initial_management = "root" } }' >/dev/null 2>&1 &
consul agent -dev -dns-port=9600 -grpc-port=9502 -grpc-tls-port=9503 -http-port=9500 -serf-lan-port=9301 -serf-wan-port=9302 -server-port=9300 >/dev/null 2>&1 &
# should be long enough for the dev agents to be available
sleep 5
# This script expects a consul dev agent with acls enabled in default allow to be running on localhost
# consul agent -dev -hcl 'acl { enabled = true default_policy="allow" tokens { initial_management = "root" } }'
# It also requires another dev agent running on alternative ports to peer with
# consul agent -dev -dns-port=9600 -grpc-port=9502 -grpc-tls-port=9503 -http-port=9500 -serf-lan-port=9301 -serf-wan-port=9302 -server-port=9300
# Just running Consul will cause the following data to be in the snapshot:
# Register
# ConnectCA
# ConnectCAProviderState
# ConnectCAConfig
# Autopilot
# Index
# SystemMetadata
# CoordinateBatchUpdate
# FederationState
# ChunkingState
# FreeVirtualIP
# Partition
# Tombstone
# Ensure a KV entry ends up in the snapshot
echo "Creating KV Entry"
consul kv put foo/bar 1 >/dev/null
# Ensure a tombstone ends up in the snapshot
echo "Forcing KV Tombstone Creation"
consul kv put foo/baz 2 >/dev/null
consul kv delete foo/baz > /dev/null
# Ensure a session ends up in the snapshot
echo "Creating Session"
curl -s -X PUT localhost:8500/v1/session/create >/dev/null
# Ensure a prepared query ends up in the snapshot
echo "Creating Prepared Query"
curl -s -X POST localhost:8500/v1/query -d '{"Name": "test", "Token": "root", "Service": {"Service": "test"}}' >/dev/null
# Ensure an ACL token ends up in the snapshot
echo "Creating ACL Token"
consul acl token create -node-identity=localhost:dc1 >/dev/null
# Ensure an ACL policy ends up in the snapshot
echo "Creating ACL Policy"
consul acl policy create -name=test -rules='node_prefix "" { policy = "write" }' >/dev/null
# Ensure an ACL role ends up in the snapshot
echo "Creating ACL Role"
consul acl role create -name=test -policy-name=test >/dev/null
# Ensure an ACL auth method ends up in the snapshot
echo "Creating ACL Auth Method"
consul acl auth-method create -type jwt -name test -config '{"JWTValidationPubKeys": ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENRw6ZwlBOx5XZKjcc1HhU00sDehc\n8nqeeSnRZLv89yT7M7qUOFDtR29FR/AFUSAEOFl1iIYLqNMElHs2VkgAZA==\n-----END PUBLIC KEY-----"]}' >/dev/null
# Ensure an ACL binding rule ends up in the snapshot
echo "Creating ACL Binding Rule"
consul acl binding-rule create -bind-type="service" -bind-name="service" -method="test" >/dev/null
# Ensure config entries end up in the snapshot
echo "Creating Proxy Default Config Entry"
consul config write - >/dev/null <<EOF
Kind = "proxy-defaults"
Name = "global"
EOF
echo "Creating Service Defaults Config Entries"
consul config write - >/dev/null <<EOF
Kind = "service-defaults"
Name = "web"
Protocol = "http"
EOF
consul config write - >/dev/null <<EOF
Kind = "service-defaults"
Name = "foo"
Protocol = "http"
EOF
echo "Creating Service Router Config Entry"
consul config write - >/dev/null <<EOF
Kind = "service-router"
Name = "foo"
Routes = [
{
Match {
HTTP {
PathPrefix = "/foo"
}
}
Destination {
Service = "web"
}
}
]
EOF
echo "Creating Service Splitter Config Entry"
consul config write - >/dev/null <<EOF
Kind = "service-splitter"
Name = "web"
Splits = [
{
Weight = 100
Service = "web"
}
]
EOF
echo "Creating Service Resolver Config Entry"
consul config write - >/dev/null <<EOF
Kind = "service-resolver"
Name = "web"
RequestTimeout = "3s"
EOF
echo "Creating Ingress Gateway Config Entry"
consul config write - >/dev/null <<EOF
Kind = "ingress-gateway"
Name = "api"
EOF
echo "Creating Terminating Gateway Config Entry"
consul config write - >/dev/null <<EOF
Kind = "terminating-gateway"
Name = "external"
Services = [
{
Name = "external"
}
]
EOF
echo "Creating Service Intentions Config Entry"
consul config write - >/dev/null <<EOF
Kind = "service-intentions"
Name = "web"
Sources = [
{
Name = "api"
Action = "allow"
}
]
EOF
echo "Creating Mesh Config Entry"
consul config write - >/dev/null <<EOF
Kind = "mesh"
AllowEnablingPermissiveMutualTLS = true
EOF
echo "Creating Exported Service Config Entry"
consul config write - >/dev/null <<EOF
Kind = "exported-services"
Name = "default"
Services = [
{
Name = "web"
Consumers = [
{
Peer = "other"
}
]
}
]
EOF
echo "Creating Inline Certificate Config Entry"
consul config write - >/dev/null <<EOF
Kind = "inline-certificate"
Name = "blah"
Certificate = "-----BEGIN CERTIFICATE-----\nMIICnjCCAkSgAwIBAgIQAxVHhSG0wSbdZm+3ToYAkDAKBggqhkjOPQQDAjCBuTEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMUAwPgYDVQQDEzdDb25zdWwgQWdlbnQgQ0Eg\nMjgwNzE4MDMxODA1Mjk2OTA1NzQ4MzU3NjI1MTI5ODQ5NDA5NjI3MCAXDTIzMTEw\nMjE1Mjk0NVoYDzIxMjMxMDA5MTUyOTQ1WjAcMRowGAYDVQQDExFjbGllbnQuZGMx\nLmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKvl1yhbsI9r7IxJxLrt\nZTNYXkCXuFy8q3gsokMqsl/MUynrIBrd9NrZEQA91ZArUYzF1+QlxM6D4hRJc5CR\n3x6jgccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr\nBgEFBQcDATAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCCvXve+zMFSJMXNS3l3YL9k\n2QH8zF74wa+TlwFSaQEjGzArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++x\nHG8dRBUpwvSk0Mk1+jAtBgNVHREEJjAkghFjbGllbnQuZGMxLmNvbnN1bIIJbG9j\nYWxob3N0hwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIBLqa1Zh3KUE0RiQzWdoYXkU\nwZo5aBw9ujqzLyAqxToFAiEAihWmc4r6lDYRR35X4QB1nTT92POJRClsfLPOTRG5\nrsU=\n-----END CERTIFICATE-----"
PrivateKey = "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINE2CQhnu7ipo67FGbEBRXoYRCTM4uJdHgNRTrdkAnHCoAoGCCqGSM49\nAwEHoUQDQgAEq+XXKFuwj2vsjEnEuu1lM1heQJe4XLyreCyiQyqyX8xTKesgGt30\n2tkRAD3VkCtRjMXX5CXEzoPiFElzkJHfHg==\n-----END EC PRIVATE KEY-----"
EOF
echo "Creating API GW Config Entry"
consul config write - >/dev/null <<EOF
Kind = "api-gateway"
Name = "apigw"
Listeners = [
{
Name = "tcp"
Port = 443
Protocol = "tcp"
TLS = {
Certificates = [
{
Kind = "inline-certificate"
Name = "blah"
}
]
}
},
{
Name = "http"
Port = 8080
Protocol = "http"
}
]
EOF
# write a sameness group config entry if this is enterprise
consul version | rg "\+ent" >/dev/null
if [ $? -eq 0 ]; then
set -e
echo "Creating Sameness Group Config Entry"
consul config write - >/dev/null <<EOF
Kind = "sameness-group"
Name = "default"
DefaultForFailover = true
IncludeLocal = true
Members = [
{
Peer = "other"
}
]
EOF
fi
echo "Creating TCP Route Config Entry"
consul config write - >/dev/null <<EOF
Kind = "tcp-route"
Name = "fake"
Parents = [
{
Kind = "api-gateway"
Name = "apigw"
SectionName = "tcp"
}
]
Services = [
{
Name = "fake"
}
]
EOF
echo "Creating HTTP Route Config Entry"
consul config write - >/dev/null <<EOF
Kind = "http-route"
Name = "web"
Parents = [
{
Kind = "api-gateway"
Name = "apigw"
SectionName = "http"
}
]
Rules = [
{
Services = [
{
Name = "fake"
}
]
}
]
EOF
echo "Creating JWT Provider Config Entry"
consul config write - >/dev/null <<EOF
Kind = "jwt-provider"
Name = "whocare"
JSONWebKeySet {
Local {
Filename = "/tmp/jwks.json"
}
}
EOF
# Ensure a peering data ends up in the snapshot
echo "Creating Peering Config Entry"
consul peering establish -http-addr=localhost:9500 -name other -peering-token="$(consul peering generate-token -name other)" >/dev/null
echo "Saving Snapshot to all.snap"
sleep 2
consul snapshot save "${SCRIPT_DIR}/all.snap" >/dev/null

View File

@ -46,6 +46,10 @@ Usage: consul snapshot <subcommand> [options] [args]
$ consul snapshot restore backup.snap
Decode a snapshot:
$ consul snapshot decode backup.snap
Inspect a snapshot:
$ consul snapshot inspect backup.snap

View File

@ -250,7 +250,7 @@ func TestBuildMultiportImplicitDestinations(t *testing.T) {
})
actual := protoToJSON(t, proxyTmpl)
expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
expected := JSONToProxyTemplate(t, golden.GetBytes(t, []byte(actual), name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
// sort routers on listener from golden file
expectedRouters := expected.ProxyState.Listeners[0].Routers

View File

@ -157,7 +157,7 @@ func TestBuildLocalApp_Multiport(t *testing.T) {
})
actual := protoToJSON(t, proxyTmpl)
expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
expected := JSONToProxyTemplate(t, golden.GetBytes(t, []byte(actual), name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
// sort routers on listener from golden file
expectedRouters := expected.ProxyState.Listeners[0].Routers

View File

@ -115,7 +115,7 @@ func TestBuildLocalApp(t *testing.T) {
})
actual := protoToJSON(t, proxyTmpl)
expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
expected := JSONToProxyTemplate(t, golden.GetBytes(t, []byte(actual), name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
// sort routers on listener from golden file
expectedRouters := expected.ProxyState.Listeners[0].Routers
@ -233,7 +233,7 @@ func TestBuildLocalApp_WithProxyConfiguration(t *testing.T) {
})
actual := protoToJSON(t, proxyTmpl)
expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
expected := JSONToProxyTemplate(t, golden.GetBytes(t, []byte(actual), name+"-"+tenancy.Partition+"-"+tenancy.Namespace+".golden"))
// sort routers on listener from golden file
expectedRouters := expected.ProxyState.Listeners[0].Routers

View File

@ -22,7 +22,7 @@ var update = flag.Bool("update", false, "update golden files")
// to the value of actual.
func Get(t *testing.T, actual, filename string) string {
t.Helper()
return string(GetBytes(t, actual, filename))
return string(GetBytes(t, []byte(actual), filename))
}
// GetBytes reads the expected value from the file at filename and returns the
@ -30,7 +30,7 @@ func Get(t *testing.T, actual, filename string) string {
//
// If the `-update` flag is used with `go test`, the golden file will be updated
// to the value of actual.
func GetBytes(t *testing.T, actual, filename string) []byte {
func GetBytes(t *testing.T, actual []byte, filename string) []byte {
t.Helper()
path := filepath.Join("testdata", filename)
@ -38,7 +38,7 @@ func GetBytes(t *testing.T, actual, filename string) []byte {
if dir := filepath.Dir(path); dir != "." {
require.NoError(t, os.MkdirAll(dir, 0755))
}
err := os.WriteFile(path, []byte(actual), 0644)
err := os.WriteFile(path, actual, 0644)
require.NoError(t, err)
}