2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
2023-08-11 13:12:13 +00:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-03-28 18:39:22 +00:00
|
|
|
|
2016-05-11 04:41:47 +00:00
|
|
|
package consul
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2022-12-14 15:24:22 +00:00
|
|
|
"context"
|
2016-05-11 04:41:47 +00:00
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2021-07-23 18:42:23 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2022-04-05 21:10:06 +00:00
|
|
|
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
|
|
|
|
|
2017-08-23 14:52:48 +00:00
|
|
|
"github.com/hashicorp/consul/acl"
|
2017-07-06 10:34:00 +00:00
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
2017-04-19 23:00:11 +00:00
|
|
|
"github.com/hashicorp/consul/api"
|
|
|
|
"github.com/hashicorp/consul/testrpc"
|
2018-12-12 13:22:25 +00:00
|
|
|
"github.com/hashicorp/consul/types"
|
2016-05-11 04:41:47 +00:00
|
|
|
)
|
|
|
|
|
2018-12-12 13:22:25 +00:00
|
|
|
var testTxnRules = `
|
|
|
|
key "" {
|
|
|
|
policy = "deny"
|
|
|
|
}
|
|
|
|
key "foo" {
|
|
|
|
policy = "read"
|
|
|
|
}
|
|
|
|
key "test" {
|
|
|
|
policy = "write"
|
|
|
|
}
|
|
|
|
key "test/priv" {
|
|
|
|
policy = "read"
|
|
|
|
}
|
|
|
|
|
|
|
|
service "" {
|
|
|
|
policy = "deny"
|
|
|
|
}
|
|
|
|
service "foo-svc" {
|
|
|
|
policy = "read"
|
|
|
|
}
|
|
|
|
service "test-svc" {
|
|
|
|
policy = "write"
|
|
|
|
}
|
|
|
|
|
|
|
|
node "" {
|
|
|
|
policy = "deny"
|
|
|
|
}
|
|
|
|
node "foo-node" {
|
|
|
|
policy = "read"
|
|
|
|
}
|
|
|
|
node "test-node" {
|
|
|
|
policy = "write"
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
var testNodeID = "9749a7df-fac5-46b4-8078-32a3d96c59f3"
|
|
|
|
|
2017-04-21 00:50:52 +00:00
|
|
|
func TestTxn_CheckNotExists(t *testing.T) {
|
2020-12-07 18:42:55 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("too slow for testing.Short")
|
|
|
|
}
|
|
|
|
|
2017-06-27 13:22:18 +00:00
|
|
|
t.Parallel()
|
2017-04-21 00:50:52 +00:00
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
|
|
|
|
|
|
|
testrpc.WaitForLeader(t, s1.RPC, "dc1")
|
|
|
|
|
|
|
|
apply := func(arg *structs.TxnRequest) (*structs.TxnResponse, error) {
|
|
|
|
out := new(structs.TxnResponse)
|
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", arg, out)
|
|
|
|
return out, err
|
|
|
|
}
|
|
|
|
|
|
|
|
checkKeyNotExists := &structs.TxnRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Ops: structs.TxnOps{
|
|
|
|
{
|
|
|
|
KV: &structs.TxnKVOp{
|
|
|
|
Verb: api.KVCheckNotExists,
|
|
|
|
DirEnt: structs.DirEntry{Key: "test"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
createKey := &structs.TxnRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Ops: structs.TxnOps{
|
|
|
|
{
|
|
|
|
KV: &structs.TxnKVOp{
|
|
|
|
Verb: api.KVSet,
|
|
|
|
DirEnt: structs.DirEntry{Key: "test"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := apply(checkKeyNotExists); err != nil {
|
|
|
|
t.Fatalf("testing for non-existent key failed: %s", err)
|
|
|
|
}
|
|
|
|
if _, err := apply(createKey); err != nil {
|
|
|
|
t.Fatalf("creating new key failed: %s", err)
|
|
|
|
}
|
|
|
|
out, err := apply(checkKeyNotExists)
|
|
|
|
if err != nil || out == nil || len(out.Errors) != 1 || out.Errors[0].Error() != `op 0: key "test" exists` {
|
|
|
|
t.Fatalf("testing for existent key failed: %#v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 04:41:47 +00:00
|
|
|
func TestTxn_Apply(t *testing.T) {
|
2020-12-07 18:42:55 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("too slow for testing.Short")
|
|
|
|
}
|
|
|
|
|
2017-06-27 13:22:18 +00:00
|
|
|
t.Parallel()
|
2016-05-11 04:41:47 +00:00
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
|
|
|
|
2017-04-19 23:00:11 +00:00
|
|
|
testrpc.WaitForLeader(t, s1.RPC, "dc1")
|
2016-05-11 04:41:47 +00:00
|
|
|
|
|
|
|
// Do a super basic request. The state store test covers the details so
|
|
|
|
// we just need to be sure that the transaction is sent correctly and
|
|
|
|
// the results are converted appropriately.
|
2016-05-11 08:35:27 +00:00
|
|
|
arg := structs.TxnRequest{
|
2016-05-11 04:41:47 +00:00
|
|
|
Datacenter: "dc1",
|
2016-05-11 08:35:27 +00:00
|
|
|
Ops: structs.TxnOps{
|
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVSet,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
Flags: 42,
|
|
|
|
Value: []byte("test"),
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVGet,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2018-12-12 13:22:25 +00:00
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeSet,
|
|
|
|
Node: structs.Node{
|
|
|
|
ID: types.NodeID(testNodeID),
|
|
|
|
Node: "foo",
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeGet,
|
|
|
|
Node: structs.Node{
|
|
|
|
ID: types.NodeID(testNodeID),
|
|
|
|
Node: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceSet,
|
|
|
|
Node: "foo",
|
|
|
|
Service: structs.NodeService{
|
|
|
|
ID: "svc-foo",
|
|
|
|
Service: "svc-foo",
|
|
|
|
Address: "1.1.1.1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceGet,
|
|
|
|
Node: "foo",
|
|
|
|
Service: structs.NodeService{
|
|
|
|
ID: "svc-foo",
|
|
|
|
Service: "svc-foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckSet,
|
|
|
|
Check: structs.HealthCheck{
|
|
|
|
Node: "foo",
|
|
|
|
CheckID: types.CheckID("check-foo"),
|
|
|
|
Name: "test",
|
|
|
|
Status: "passing",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckGet,
|
|
|
|
Check: structs.HealthCheck{
|
|
|
|
Node: "foo",
|
|
|
|
CheckID: types.CheckID("check-foo"),
|
|
|
|
Name: "test",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
}
|
2016-05-11 08:35:27 +00:00
|
|
|
var out structs.TxnResponse
|
2016-05-11 04:41:47 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2018-12-12 13:22:25 +00:00
|
|
|
if len(out.Errors) != 0 {
|
|
|
|
t.Fatalf("errs: %v", out.Errors)
|
|
|
|
}
|
2016-05-11 04:41:47 +00:00
|
|
|
|
|
|
|
// Verify the state store directly.
|
|
|
|
state := s1.fsm.State()
|
2019-11-25 17:57:35 +00:00
|
|
|
_, d, err := state.KVSGet(nil, "test", nil)
|
2016-05-11 04:41:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if d == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
|
|
|
if d.Flags != 42 ||
|
|
|
|
!bytes.Equal(d.Value, []byte("test")) {
|
|
|
|
t.Fatalf("bad: %v", d)
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
_, n, err := state.GetNode("foo", nil, "")
|
2018-12-12 13:22:25 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if n.Node != "foo" || n.Address != "127.0.0.1" {
|
|
|
|
t.Fatalf("bad: %v", err)
|
|
|
|
}
|
|
|
|
|
2022-05-27 11:38:52 +00:00
|
|
|
_, s, err := state.NodeService(nil, "foo", "svc-foo", nil, "")
|
2018-12-12 13:22:25 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if s.ID != "svc-foo" || s.Address != "1.1.1.1" {
|
|
|
|
t.Fatalf("bad: %v", err)
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
_, c, err := state.NodeCheck("foo", types.CheckID("check-foo"), nil, "")
|
2018-12-12 13:22:25 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if c.CheckID != "check-foo" || c.Status != "passing" || c.Name != "test" {
|
|
|
|
t.Fatalf("bad: %v", err)
|
|
|
|
}
|
|
|
|
|
2016-05-11 04:41:47 +00:00
|
|
|
// Verify the transaction's return value.
|
2016-05-11 08:35:27 +00:00
|
|
|
expected := structs.TxnResponse{
|
|
|
|
Results: structs.TxnResults{
|
|
|
|
&structs.TxnResult{
|
2016-05-11 20:48:03 +00:00
|
|
|
KV: &structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
Flags: 42,
|
|
|
|
Value: nil,
|
|
|
|
RaftIndex: structs.RaftIndex{
|
|
|
|
CreateIndex: d.CreateIndex,
|
|
|
|
ModifyIndex: d.ModifyIndex,
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2019-11-25 17:57:35 +00:00
|
|
|
EnterpriseMeta: d.EnterpriseMeta,
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnResult{
|
2016-05-11 20:48:03 +00:00
|
|
|
KV: &structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
Flags: 42,
|
|
|
|
Value: []byte("test"),
|
|
|
|
RaftIndex: structs.RaftIndex{
|
|
|
|
CreateIndex: d.CreateIndex,
|
|
|
|
ModifyIndex: d.ModifyIndex,
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2019-11-25 17:57:35 +00:00
|
|
|
EnterpriseMeta: d.EnterpriseMeta,
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2018-12-12 13:22:25 +00:00
|
|
|
&structs.TxnResult{
|
|
|
|
Node: n,
|
|
|
|
},
|
|
|
|
&structs.TxnResult{
|
|
|
|
Node: n,
|
|
|
|
},
|
|
|
|
&structs.TxnResult{
|
|
|
|
Service: s,
|
|
|
|
},
|
|
|
|
&structs.TxnResult{
|
|
|
|
Service: s,
|
|
|
|
},
|
|
|
|
&structs.TxnResult{
|
|
|
|
Check: c,
|
|
|
|
},
|
|
|
|
&structs.TxnResult{
|
|
|
|
Check: c,
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
}
|
2019-11-25 17:57:35 +00:00
|
|
|
require.Equal(t, expected, out)
|
2016-05-11 04:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTxn_Apply_ACLDeny(t *testing.T) {
|
2020-12-07 18:42:55 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("too slow for testing.Short")
|
|
|
|
}
|
|
|
|
|
2017-06-27 13:22:18 +00:00
|
|
|
t.Parallel()
|
2018-12-12 13:22:25 +00:00
|
|
|
|
2016-05-11 04:41:47 +00:00
|
|
|
dir1, s1 := testServerWithConfig(t, func(c *Config) {
|
2021-08-06 22:00:58 +00:00
|
|
|
c.PrimaryDatacenter = "dc1"
|
2018-10-19 16:04:07 +00:00
|
|
|
c.ACLsEnabled = true
|
2021-12-07 12:39:28 +00:00
|
|
|
c.ACLInitialManagementToken = "root"
|
2021-08-06 22:39:39 +00:00
|
|
|
c.ACLResolverSettings.ACLDefaultPolicy = "deny"
|
2016-05-11 04:41:47 +00:00
|
|
|
})
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
|
2017-04-19 23:00:11 +00:00
|
|
|
testrpc.WaitForLeader(t, s1.RPC, "dc1")
|
2016-05-11 04:41:47 +00:00
|
|
|
|
2018-12-12 13:22:25 +00:00
|
|
|
// Set up some state to read back.
|
2016-05-13 22:58:55 +00:00
|
|
|
state := s1.fsm.State()
|
|
|
|
d := &structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
Value: []byte("hello"),
|
|
|
|
}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, state.KVSSet(1, d))
|
2018-12-12 13:22:25 +00:00
|
|
|
|
|
|
|
node := &structs.Node{
|
|
|
|
ID: types.NodeID(testNodeID),
|
|
|
|
Node: "nope",
|
2016-05-13 22:58:55 +00:00
|
|
|
}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, state.EnsureNode(2, node))
|
2018-12-12 13:22:25 +00:00
|
|
|
|
|
|
|
svc := structs.NodeService{ID: "nope", Service: "nope", Address: "127.0.0.1"}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, state.EnsureService(3, "nope", &svc))
|
2018-12-12 13:22:25 +00:00
|
|
|
|
|
|
|
check := structs.HealthCheck{Node: "nope", CheckID: types.CheckID("nope")}
|
|
|
|
state.EnsureCheck(4, &check)
|
2016-05-13 22:58:55 +00:00
|
|
|
|
2022-03-18 17:32:25 +00:00
|
|
|
token := createTokenFull(t, rpcClient(t, s1), testTxnRules)
|
|
|
|
id := token.SecretID
|
2016-05-11 04:41:47 +00:00
|
|
|
|
|
|
|
// Set up a transaction where every operation should get blocked due to
|
|
|
|
// ACLs.
|
2016-05-11 08:35:27 +00:00
|
|
|
arg := structs.TxnRequest{
|
2016-05-11 04:41:47 +00:00
|
|
|
Datacenter: "dc1",
|
2016-05-11 08:35:27 +00:00
|
|
|
Ops: structs.TxnOps{
|
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVSet,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
2016-05-13 22:58:55 +00:00
|
|
|
Key: "nope",
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVDelete,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
2016-05-13 22:58:55 +00:00
|
|
|
Key: "nope",
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVDeleteCAS,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
2016-05-13 22:58:55 +00:00
|
|
|
Key: "nope",
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVDeleteTree,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
2016-05-13 22:58:55 +00:00
|
|
|
Key: "nope",
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVCAS,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
2016-05-13 22:58:55 +00:00
|
|
|
Key: "nope",
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVLock,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
2016-05-13 22:58:55 +00:00
|
|
|
Key: "nope",
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVUnlock,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
2016-05-13 22:58:55 +00:00
|
|
|
Key: "nope",
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVGet,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-13 23:57:39 +00:00
|
|
|
&structs.TxnOp{
|
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVGetTree,
|
2016-05-13 23:57:39 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVCheckSession,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-11 08:35:27 +00:00
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVCheckIndex,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
2017-04-21 00:50:52 +00:00
|
|
|
&structs.TxnOp{
|
|
|
|
KV: &structs.TxnKVOp{
|
|
|
|
Verb: api.KVCheckNotExists,
|
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2018-12-12 13:22:25 +00:00
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeGet,
|
|
|
|
Node: structs.Node{ID: node.ID, Node: node.Node},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeSet,
|
|
|
|
Node: structs.Node{ID: node.ID, Node: node.Node},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeCAS,
|
|
|
|
Node: structs.Node{ID: node.ID, Node: node.Node},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeDelete,
|
|
|
|
Node: structs.Node{ID: node.ID, Node: node.Node},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeDeleteCAS,
|
|
|
|
Node: structs.Node{ID: node.ID, Node: node.Node},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceGet,
|
|
|
|
Node: "foo-node",
|
|
|
|
Service: svc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceSet,
|
|
|
|
Node: "foo-node",
|
|
|
|
Service: svc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceCAS,
|
|
|
|
Node: "foo-node",
|
|
|
|
Service: svc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceDelete,
|
|
|
|
Node: "foo-node",
|
|
|
|
Service: svc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceDeleteCAS,
|
|
|
|
Node: "foo-node",
|
|
|
|
Service: svc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckGet,
|
|
|
|
Check: check,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckSet,
|
|
|
|
Check: check,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckCAS,
|
|
|
|
Check: check,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckDelete,
|
|
|
|
Check: check,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckDeleteCAS,
|
|
|
|
Check: check,
|
|
|
|
},
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
2016-05-13 00:38:25 +00:00
|
|
|
WriteRequest: structs.WriteRequest{
|
|
|
|
Token: id,
|
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
}
|
2016-05-11 08:35:27 +00:00
|
|
|
var out structs.TxnResponse
|
2022-12-14 15:24:22 +00:00
|
|
|
if err := s1.RPC(context.Background(), "Txn.Apply", &arg, &out); err != nil {
|
2016-05-11 04:41:47 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the transaction's return value.
|
2022-03-11 02:48:27 +00:00
|
|
|
var outPos int
|
2016-05-13 22:58:55 +00:00
|
|
|
for i, op := range arg.Ops {
|
2022-03-11 02:48:27 +00:00
|
|
|
err := out.Errors[outPos]
|
2018-12-12 13:22:25 +00:00
|
|
|
switch {
|
|
|
|
case op.KV != nil:
|
|
|
|
switch op.KV.Verb {
|
|
|
|
case api.KVGet, api.KVGetTree:
|
|
|
|
// These get filtered but won't result in an error.
|
2022-03-11 02:48:27 +00:00
|
|
|
case api.KVSet, api.KVDelete, api.KVDeleteCAS, api.KVDeleteTree, api.KVCAS, api.KVLock, api.KVUnlock, api.KVCheckNotExists:
|
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceKey, acl.AccessWrite, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
default:
|
2022-03-11 02:48:27 +00:00
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceKey, acl.AccessRead, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
}
|
|
|
|
case op.Node != nil:
|
|
|
|
switch op.Node.Verb {
|
|
|
|
case api.NodeGet:
|
|
|
|
// These get filtered but won't result in an error.
|
2022-03-11 02:48:27 +00:00
|
|
|
case api.NodeSet, api.NodeDelete, api.NodeDeleteCAS, api.NodeCAS:
|
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceNode, acl.AccessWrite, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
default:
|
2022-03-11 02:48:27 +00:00
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceNode, acl.AccessRead, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
}
|
|
|
|
case op.Service != nil:
|
|
|
|
switch op.Service.Verb {
|
|
|
|
case api.ServiceGet:
|
|
|
|
// These get filtered but won't result in an error.
|
2022-03-11 02:48:27 +00:00
|
|
|
case api.ServiceSet, api.ServiceCAS, api.ServiceDelete, api.ServiceDeleteCAS:
|
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceService, acl.AccessWrite, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
default:
|
2022-03-11 02:48:27 +00:00
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceService, acl.AccessRead, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
}
|
|
|
|
case op.Check != nil:
|
|
|
|
switch op.Check.Verb {
|
|
|
|
case api.CheckGet:
|
|
|
|
// These get filtered but won't result in an error.
|
2022-03-11 02:48:27 +00:00
|
|
|
case api.CheckSet, api.CheckCAS, api.CheckDelete, api.CheckDeleteCAS:
|
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceNode, acl.AccessWrite, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
default:
|
2022-03-11 02:48:27 +00:00
|
|
|
require.Equal(t, err.OpIndex, i)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, err.What, token.AccessorID, nil, acl.ResourceNode, acl.AccessRead, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
outPos++
|
2018-12-12 13:22:25 +00:00
|
|
|
}
|
2016-05-13 22:58:55 +00:00
|
|
|
}
|
2016-05-11 04:41:47 +00:00
|
|
|
}
|
|
|
|
}
|
2016-05-13 00:38:25 +00:00
|
|
|
|
2016-05-11 04:41:47 +00:00
|
|
|
func TestTxn_Apply_LockDelay(t *testing.T) {
|
2020-12-07 18:42:55 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("too slow for testing.Short")
|
|
|
|
}
|
|
|
|
|
2017-06-27 13:22:18 +00:00
|
|
|
t.Parallel()
|
2016-05-11 04:41:47 +00:00
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
|
|
|
|
2019-11-25 17:07:04 +00:00
|
|
|
testrpc.WaitForTestAgent(t, s1.RPC, "dc1")
|
2016-05-11 04:41:47 +00:00
|
|
|
|
|
|
|
// Create and invalidate a session with a lock.
|
|
|
|
state := s1.fsm.State()
|
|
|
|
if err := state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
session := &structs.Session{
|
|
|
|
ID: generateUUID(),
|
|
|
|
Node: "foo",
|
|
|
|
LockDelay: 50 * time.Millisecond,
|
|
|
|
}
|
|
|
|
if err := state.SessionCreate(2, session); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
id := session.ID
|
|
|
|
d := &structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
Session: id,
|
|
|
|
}
|
|
|
|
if ok, err := state.KVSLock(3, d); err != nil || !ok {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2019-11-25 17:07:04 +00:00
|
|
|
|
|
|
|
if err := state.SessionDestroy(4, id, nil); err != nil {
|
2016-05-11 04:41:47 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make a new session that is valid.
|
|
|
|
if err := state.SessionCreate(5, session); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2017-04-21 00:02:42 +00:00
|
|
|
validID := session.ID
|
2016-05-11 04:41:47 +00:00
|
|
|
|
|
|
|
// Make a lock request via an atomic transaction.
|
2016-05-11 08:35:27 +00:00
|
|
|
arg := structs.TxnRequest{
|
2016-05-11 04:41:47 +00:00
|
|
|
Datacenter: "dc1",
|
2016-05-11 08:35:27 +00:00
|
|
|
Ops: structs.TxnOps{
|
|
|
|
&structs.TxnOp{
|
2016-05-11 17:58:27 +00:00
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVLock,
|
2016-05-11 08:35:27 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "test",
|
2017-04-21 00:02:42 +00:00
|
|
|
Session: validID,
|
2016-05-11 08:35:27 +00:00
|
|
|
},
|
2016-05-11 04:41:47 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
{
|
2016-05-11 08:35:27 +00:00
|
|
|
var out structs.TxnResponse
|
2016-05-11 04:41:47 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if len(out.Results) != 0 ||
|
|
|
|
len(out.Errors) != 1 ||
|
|
|
|
out.Errors[0].OpIndex != 0 ||
|
|
|
|
!strings.Contains(out.Errors[0].What, "due to lock delay") {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for lock-delay.
|
|
|
|
time.Sleep(50 * time.Millisecond)
|
|
|
|
|
|
|
|
// Should acquire.
|
|
|
|
{
|
2016-05-11 08:35:27 +00:00
|
|
|
var out structs.TxnResponse
|
2016-05-11 04:41:47 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if len(out.Results) != 1 ||
|
|
|
|
len(out.Errors) != 0 ||
|
2016-05-11 20:48:03 +00:00
|
|
|
out.Results[0].KV.LockIndex != 2 {
|
2016-05-11 04:41:47 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-13 00:38:25 +00:00
|
|
|
|
|
|
|
func TestTxn_Read(t *testing.T) {
|
2020-12-07 18:42:55 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("too slow for testing.Short")
|
|
|
|
}
|
|
|
|
|
2017-06-27 13:22:18 +00:00
|
|
|
t.Parallel()
|
2018-12-12 13:22:25 +00:00
|
|
|
|
2016-05-13 00:38:25 +00:00
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
|
|
|
|
2017-04-19 23:00:11 +00:00
|
|
|
testrpc.WaitForLeader(t, s1.RPC, "dc1")
|
2016-05-13 00:38:25 +00:00
|
|
|
|
|
|
|
// Put in a key to read back.
|
|
|
|
state := s1.fsm.State()
|
|
|
|
d := &structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
Value: []byte("hello"),
|
|
|
|
}
|
|
|
|
if err := state.KVSSet(1, d); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2018-12-12 13:22:25 +00:00
|
|
|
// Put in a node/check/service to read back.
|
|
|
|
node := &structs.Node{
|
|
|
|
ID: types.NodeID(testNodeID),
|
|
|
|
Node: "foo",
|
|
|
|
}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, state.EnsureNode(2, node))
|
2018-12-12 13:22:25 +00:00
|
|
|
|
2019-12-10 02:26:41 +00:00
|
|
|
svc := structs.NodeService{
|
|
|
|
ID: "svc-foo",
|
|
|
|
Service: "svc-foo",
|
|
|
|
Address: "127.0.0.1",
|
2021-07-22 18:20:45 +00:00
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
|
2019-12-10 02:26:41 +00:00
|
|
|
}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, state.EnsureService(3, "foo", &svc))
|
2018-12-12 13:22:25 +00:00
|
|
|
|
2019-12-10 02:26:41 +00:00
|
|
|
check := structs.HealthCheck{
|
|
|
|
Node: "foo",
|
|
|
|
CheckID: types.CheckID("check-foo"),
|
2021-07-22 18:20:45 +00:00
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
|
2019-12-10 02:26:41 +00:00
|
|
|
}
|
2018-12-12 13:22:25 +00:00
|
|
|
state.EnsureCheck(4, &check)
|
|
|
|
|
2016-05-13 00:38:25 +00:00
|
|
|
// Do a super basic request. The state store test covers the details so
|
|
|
|
// we just need to be sure that the transaction is sent correctly and
|
|
|
|
// the results are converted appropriately.
|
|
|
|
arg := structs.TxnReadRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Ops: structs.TxnOps{
|
|
|
|
&structs.TxnOp{
|
|
|
|
KV: &structs.TxnKVOp{
|
2017-04-19 23:00:11 +00:00
|
|
|
Verb: api.KVGet,
|
2016-05-13 00:38:25 +00:00
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2018-12-12 13:22:25 +00:00
|
|
|
&structs.TxnOp{
|
|
|
|
Node: &structs.TxnNodeOp{
|
|
|
|
Verb: api.NodeGet,
|
|
|
|
Node: structs.Node{ID: node.ID, Node: node.Node},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Service: &structs.TxnServiceOp{
|
|
|
|
Verb: api.ServiceGet,
|
|
|
|
Node: "foo",
|
|
|
|
Service: svc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.TxnOp{
|
|
|
|
Check: &structs.TxnCheckOp{
|
|
|
|
Verb: api.CheckGet,
|
|
|
|
Check: check,
|
|
|
|
},
|
|
|
|
},
|
2016-05-13 00:38:25 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
var out structs.TxnReadResponse
|
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the transaction's return value.
|
2018-12-12 13:22:25 +00:00
|
|
|
svc.Weights = &structs.Weights{Passing: 1, Warning: 1}
|
|
|
|
svc.RaftIndex = structs.RaftIndex{CreateIndex: 3, ModifyIndex: 3}
|
2019-11-25 17:57:35 +00:00
|
|
|
|
|
|
|
entMeta := out.Results[0].KV.EnterpriseMeta
|
2016-05-13 00:38:25 +00:00
|
|
|
expected := structs.TxnReadResponse{
|
|
|
|
TxnResponse: structs.TxnResponse{
|
|
|
|
Results: structs.TxnResults{
|
|
|
|
&structs.TxnResult{
|
|
|
|
KV: &structs.DirEntry{
|
|
|
|
Key: "test",
|
|
|
|
Value: []byte("hello"),
|
|
|
|
RaftIndex: structs.RaftIndex{
|
|
|
|
CreateIndex: 1,
|
|
|
|
ModifyIndex: 1,
|
|
|
|
},
|
2019-11-25 17:57:35 +00:00
|
|
|
EnterpriseMeta: entMeta,
|
2016-05-13 00:38:25 +00:00
|
|
|
},
|
|
|
|
},
|
2018-12-12 13:22:25 +00:00
|
|
|
&structs.TxnResult{
|
|
|
|
Node: node,
|
|
|
|
},
|
|
|
|
&structs.TxnResult{
|
|
|
|
Service: &svc,
|
|
|
|
},
|
|
|
|
&structs.TxnResult{
|
|
|
|
Check: &check,
|
|
|
|
},
|
2016-05-13 00:38:25 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
QueryMeta: structs.QueryMeta{
|
|
|
|
KnownLeader: true,
|
2022-01-17 20:09:08 +00:00
|
|
|
Index: 1,
|
2016-05-13 00:38:25 +00:00
|
|
|
},
|
|
|
|
}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.Equal(t, expected, out)
|
2016-05-13 00:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTxn_Read_ACLDeny(t *testing.T) {
|
2020-12-07 18:42:55 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("too slow for testing.Short")
|
|
|
|
}
|
|
|
|
|
2017-06-27 13:22:18 +00:00
|
|
|
t.Parallel()
|
2018-12-12 13:22:25 +00:00
|
|
|
|
2016-05-13 00:38:25 +00:00
|
|
|
dir1, s1 := testServerWithConfig(t, func(c *Config) {
|
2021-08-06 22:00:58 +00:00
|
|
|
c.PrimaryDatacenter = "dc1"
|
2018-10-19 16:04:07 +00:00
|
|
|
c.ACLsEnabled = true
|
2021-12-07 12:39:28 +00:00
|
|
|
c.ACLInitialManagementToken = "root"
|
2021-08-06 22:39:39 +00:00
|
|
|
c.ACLResolverSettings.ACLDefaultPolicy = "deny"
|
2016-05-13 00:38:25 +00:00
|
|
|
})
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
|
|
|
|
2017-04-19 23:00:11 +00:00
|
|
|
testrpc.WaitForLeader(t, s1.RPC, "dc1")
|
2016-05-13 00:38:25 +00:00
|
|
|
|
2016-05-13 22:58:55 +00:00
|
|
|
// Put in a key to read back.
|
|
|
|
state := s1.fsm.State()
|
|
|
|
d := &structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
Value: []byte("hello"),
|
|
|
|
}
|
|
|
|
if err := state.KVSSet(1, d); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2018-12-12 13:22:25 +00:00
|
|
|
// Put in a node/check/service to read back.
|
|
|
|
node := &structs.Node{
|
|
|
|
ID: types.NodeID(testNodeID),
|
|
|
|
Node: "nope",
|
|
|
|
}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, state.EnsureNode(2, node))
|
2018-12-12 13:22:25 +00:00
|
|
|
|
|
|
|
svc := structs.NodeService{ID: "nope", Service: "nope", Address: "127.0.0.1"}
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, state.EnsureService(3, "nope", &svc))
|
2018-12-12 13:22:25 +00:00
|
|
|
|
|
|
|
check := structs.HealthCheck{Node: "nope", CheckID: types.CheckID("nope")}
|
|
|
|
state.EnsureCheck(4, &check)
|
|
|
|
|
2022-03-18 17:32:25 +00:00
|
|
|
token := createTokenFull(t, codec, testTxnRules)
|
2016-05-13 00:38:25 +00:00
|
|
|
|
2021-12-03 20:41:03 +00:00
|
|
|
t.Run("simple read operations (results get filtered out)", func(t *testing.T) {
|
|
|
|
arg := structs.TxnReadRequest{
|
|
|
|
Datacenter: "dc1",
|
2022-03-23 03:41:13 +00:00
|
|
|
QueryOptions: structs.QueryOptions{Token: token.SecretID},
|
2021-12-03 20:41:03 +00:00
|
|
|
Ops: structs.TxnOps{
|
|
|
|
{
|
|
|
|
KV: &structs.TxnKVOp{
|
|
|
|
Verb: api.KVGet,
|
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
2016-05-13 00:38:25 +00:00
|
|
|
},
|
|
|
|
},
|
2021-12-03 20:41:03 +00:00
|
|
|
{
|
|
|
|
KV: &structs.TxnKVOp{
|
|
|
|
Verb: api.KVGetTree,
|
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
2016-05-13 23:57:39 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-12-03 20:41:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var out structs.TxnReadResponse
|
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &arg, &out)
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, out.Results)
|
|
|
|
require.Empty(t, out.Errors)
|
|
|
|
require.True(t, out.QueryMeta.ResultsFilteredByACLs, "ResultsFilteredByACLs should be true")
|
2021-12-03 20:41:03 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("complex operations (return permission denied errors)", func(t *testing.T) {
|
|
|
|
arg := structs.TxnReadRequest{
|
|
|
|
Datacenter: "dc1",
|
2022-03-23 03:41:13 +00:00
|
|
|
QueryOptions: structs.QueryOptions{Token: token.SecretID},
|
2021-12-03 20:41:03 +00:00
|
|
|
Ops: structs.TxnOps{
|
|
|
|
{
|
|
|
|
KV: &structs.TxnKVOp{
|
|
|
|
Verb: api.KVCheckSession,
|
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
2016-05-13 00:38:25 +00:00
|
|
|
},
|
|
|
|
},
|
2021-12-03 20:41:03 +00:00
|
|
|
{
|
|
|
|
KV: &structs.TxnKVOp{
|
|
|
|
Verb: api.KVCheckIndex,
|
|
|
|
DirEnt: structs.DirEntry{
|
|
|
|
Key: "nope",
|
|
|
|
},
|
2016-05-13 00:38:25 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-05-13 22:58:55 +00:00
|
|
|
}
|
2021-12-03 20:41:03 +00:00
|
|
|
|
|
|
|
var out structs.TxnReadResponse
|
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &arg, &out)
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.NoError(t, err)
|
2022-03-18 17:32:25 +00:00
|
|
|
acl.RequirePermissionDeniedMessage(t, out.Errors[0].What, token.AccessorID, nil, acl.ResourceKey, acl.AccessRead, "nope")
|
|
|
|
acl.RequirePermissionDeniedMessage(t, out.Errors[1].What, token.AccessorID, nil, acl.ResourceKey, acl.AccessRead, "nope")
|
2022-03-11 02:48:27 +00:00
|
|
|
|
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
|
|
|
require.Empty(t, out.Results)
|
2021-12-03 20:41:03 +00:00
|
|
|
})
|
2016-05-13 00:38:25 +00:00
|
|
|
}
|