mirror of https://github.com/k3s-io/k3s
Update etcd client to 3.2.24 for latest release
Signed-off-by: Timothy St. Clair <timothysc@gmail.com>pull/8/head
parent
674401ace1
commit
0bb21f647f
File diff suppressed because it is too large
Load Diff
|
@ -48,295 +48,295 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/alarm",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/auth",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/client",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/compactor",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/discovery",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/embed",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/error",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/integration",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/lease",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/monotime",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/raft",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/snap",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/store",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/version",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/wal",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-semver/semver",
|
||||
|
|
|
@ -44,295 +44,295 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/alarm",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/auth",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/client",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/compactor",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/discovery",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/embed",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/error",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/integration",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/lease",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/monotime",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/raft",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/snap",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/store",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/version",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/wal",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-oidc",
|
||||
|
|
|
@ -36,51 +36,51 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/client",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/version",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-semver/semver",
|
||||
|
|
|
@ -36,51 +36,51 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/client",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/etcd/version",
|
||||
"Rev": "95a726a27e09030f9ccbd9982a1508f5a6d25ada"
|
||||
"Rev": "420a452267a7ce45b3fcbed04d54030d69964fc1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-semver/semver",
|
||||
|
|
|
@ -118,6 +118,11 @@ func (t *tokenSimple) genTokenPrefix() (string, error) {
|
|||
|
||||
func (t *tokenSimple) assignSimpleTokenToUser(username, token string) {
|
||||
t.simpleTokensMu.Lock()
|
||||
defer t.simpleTokensMu.Unlock()
|
||||
if t.simpleTokenKeeper == nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := t.simpleTokens[token]
|
||||
if ok {
|
||||
plog.Panicf("token %s is alredy used", token)
|
||||
|
@ -125,7 +130,6 @@ func (t *tokenSimple) assignSimpleTokenToUser(username, token string) {
|
|||
|
||||
t.simpleTokens[token] = username
|
||||
t.simpleTokenKeeper.addSimpleToken(token)
|
||||
t.simpleTokensMu.Unlock()
|
||||
}
|
||||
|
||||
func (t *tokenSimple) invalidateUser(username string) {
|
||||
|
|
|
@ -10,13 +10,13 @@ go_library(
|
|||
"compare.go",
|
||||
"config.go",
|
||||
"doc.go",
|
||||
"grpc_options.go",
|
||||
"health_balancer.go",
|
||||
"kv.go",
|
||||
"lease.go",
|
||||
"logger.go",
|
||||
"maintenance.go",
|
||||
"op.go",
|
||||
"options.go",
|
||||
"ready_wait.go",
|
||||
"retry.go",
|
||||
"sort.go",
|
||||
|
@ -31,6 +31,7 @@ go_library(
|
|||
"//vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/etcdserver/etcdserverpb:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/mvcc/mvccpb:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/types:go_default_library",
|
||||
"//vendor/golang.org/x/net/context:go_default_library",
|
||||
"//vendor/google.golang.org/grpc:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/codes:go_default_library",
|
||||
|
|
|
@ -529,6 +529,20 @@ func isHaltErr(ctx context.Context, err error) bool {
|
|||
return ev.Code() != codes.Unavailable && ev.Code() != codes.Internal
|
||||
}
|
||||
|
||||
// isUnavailableErr returns true if the given error is an unavailable error
|
||||
func isUnavailableErr(ctx context.Context, err error) bool {
|
||||
if ctx != nil && ctx.Err() != nil {
|
||||
return false
|
||||
}
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
ev, _ := status.FromError(err)
|
||||
// Unavailable codes mean the system will be right back.
|
||||
// (e.g., can't connect, lost leader)
|
||||
return ev.Code() == codes.Unavailable
|
||||
}
|
||||
|
||||
func toErr(ctx context.Context, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
|
|
|
@ -16,6 +16,7 @@ package clientv3
|
|||
|
||||
import (
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -65,6 +66,11 @@ func NewClusterFromClusterClient(remote pb.ClusterClient, c *Client) Cluster {
|
|||
}
|
||||
|
||||
func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) {
|
||||
// fail-fast before panic in rafthttp
|
||||
if _, err := types.NewURLs(peerAddrs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := &pb.MemberAddRequest{PeerURLs: peerAddrs}
|
||||
resp, err := c.remote.MemberAdd(ctx, r, c.callOpts...)
|
||||
if err != nil {
|
||||
|
@ -83,6 +89,11 @@ func (c *cluster) MemberRemove(ctx context.Context, id uint64) (*MemberRemoveRes
|
|||
}
|
||||
|
||||
func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error) {
|
||||
// fail-fast before panic in rafthttp
|
||||
if _, err := types.NewURLs(peerAddrs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// it is safe to retry on update.
|
||||
r := &pb.MemberUpdateRequest{ID: id, PeerURLs: peerAddrs}
|
||||
resp, err := c.remote.MemberUpdate(ctx, r, c.callOpts...)
|
||||
|
|
|
@ -71,8 +71,6 @@ const (
|
|||
// defaultTTL is the assumed lease TTL used for the first keepalive
|
||||
// deadline before the actual TTL is known to the client.
|
||||
defaultTTL = 5 * time.Second
|
||||
// a small buffer to store unsent lease responses.
|
||||
leaseResponseChSize = 16
|
||||
// NoLease is a lease ID for the absence of a lease.
|
||||
NoLease LeaseID = 0
|
||||
|
||||
|
@ -80,6 +78,11 @@ const (
|
|||
retryConnWait = 500 * time.Millisecond
|
||||
)
|
||||
|
||||
// LeaseResponseChSize is the size of buffer to store unsent lease responses.
|
||||
// WARNING: DO NOT UPDATE.
|
||||
// Only for testing purposes.
|
||||
var LeaseResponseChSize = 16
|
||||
|
||||
// ErrKeepAliveHalted is returned if client keep alive loop halts with an unexpected error.
|
||||
//
|
||||
// This usually means that automatic lease renewal via KeepAlive is broken, but KeepAliveOnce will still work as expected.
|
||||
|
@ -219,7 +222,7 @@ func (l *lessor) TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption
|
|||
}
|
||||
|
||||
func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) {
|
||||
ch := make(chan *LeaseKeepAliveResponse, leaseResponseChSize)
|
||||
ch := make(chan *LeaseKeepAliveResponse, LeaseResponseChSize)
|
||||
|
||||
l.mu.Lock()
|
||||
// ensure that recvKeepAliveLoop is still running
|
||||
|
@ -475,9 +478,10 @@ func (l *lessor) recvKeepAlive(resp *pb.LeaseKeepAliveResponse) {
|
|||
for _, ch := range ka.chs {
|
||||
select {
|
||||
case ch <- karesp:
|
||||
ka.nextKeepAlive = nextKeepAlive
|
||||
default:
|
||||
}
|
||||
// still advance in order to rate-limit keep-alive sends
|
||||
ka.nextKeepAlive = nextKeepAlive
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,3 +44,6 @@ var (
|
|||
// Some options are exposed to "clientv3.Config".
|
||||
// Defaults will be overridden by the settings in "clientv3.Config".
|
||||
var defaultCallOpts = []grpc.CallOption{defaultFailFast, defaultMaxCallSendMsgSize, defaultMaxCallRecvMsgSize}
|
||||
|
||||
// MaxLeaseTTL is the maximum lease TTL value
|
||||
const MaxLeaseTTL = 9000000000
|
|
@ -769,10 +769,13 @@ func (w *watchGrpcStream) joinSubstreams() {
|
|||
}
|
||||
}
|
||||
|
||||
var maxBackoff = 100 * time.Millisecond
|
||||
|
||||
// openWatchClient retries opening a watch client until success or halt.
|
||||
// manually retry in case "ws==nil && err==nil"
|
||||
// TODO: remove FailFast=false
|
||||
func (w *watchGrpcStream) openWatchClient() (ws pb.Watch_WatchClient, err error) {
|
||||
backoff := time.Millisecond
|
||||
for {
|
||||
select {
|
||||
case <-w.ctx.Done():
|
||||
|
@ -788,6 +791,17 @@ func (w *watchGrpcStream) openWatchClient() (ws pb.Watch_WatchClient, err error)
|
|||
if isHaltErr(w.ctx, err) {
|
||||
return nil, v3rpc.Error(err)
|
||||
}
|
||||
if isUnavailableErr(w.ctx, err) {
|
||||
// retry, but backoff
|
||||
if backoff < maxBackoff {
|
||||
// 25% backoff factor
|
||||
backoff = backoff + backoff/4
|
||||
if backoff > maxBackoff {
|
||||
backoff = maxBackoff
|
||||
}
|
||||
}
|
||||
time.Sleep(backoff)
|
||||
}
|
||||
}
|
||||
return ws, nil
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ go_library(
|
|||
"//vendor/github.com/coreos/etcd/pkg/netutil:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/runtime:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/srv:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/tlsutil:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/transport:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/types:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/rafthttp:go_default_library",
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -27,6 +28,7 @@ import (
|
|||
"github.com/coreos/etcd/pkg/cors"
|
||||
"github.com/coreos/etcd/pkg/netutil"
|
||||
"github.com/coreos/etcd/pkg/srv"
|
||||
"github.com/coreos/etcd/pkg/tlsutil"
|
||||
"github.com/coreos/etcd/pkg/transport"
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
|
||||
|
@ -87,8 +89,38 @@ type Config struct {
|
|||
// TickMs is the number of milliseconds between heartbeat ticks.
|
||||
// TODO: decouple tickMs and heartbeat tick (current heartbeat tick = 1).
|
||||
// make ticks a cluster wide configuration.
|
||||
TickMs uint `json:"heartbeat-interval"`
|
||||
ElectionMs uint `json:"election-timeout"`
|
||||
TickMs uint `json:"heartbeat-interval"`
|
||||
ElectionMs uint `json:"election-timeout"`
|
||||
|
||||
// InitialElectionTickAdvance is true, then local member fast-forwards
|
||||
// election ticks to speed up "initial" leader election trigger. This
|
||||
// benefits the case of larger election ticks. For instance, cross
|
||||
// datacenter deployment may require longer election timeout of 10-second.
|
||||
// If true, local node does not need wait up to 10-second. Instead,
|
||||
// forwards its election ticks to 8-second, and have only 2-second left
|
||||
// before leader election.
|
||||
//
|
||||
// Major assumptions are that:
|
||||
// - cluster has no active leader thus advancing ticks enables faster
|
||||
// leader election, or
|
||||
// - cluster already has an established leader, and rejoining follower
|
||||
// is likely to receive heartbeats from the leader after tick advance
|
||||
// and before election timeout.
|
||||
//
|
||||
// However, when network from leader to rejoining follower is congested,
|
||||
// and the follower does not receive leader heartbeat within left election
|
||||
// ticks, disruptive election has to happen thus affecting cluster
|
||||
// availabilities.
|
||||
//
|
||||
// Disabling this would slow down initial bootstrap process for cross
|
||||
// datacenter deployments. Make your own tradeoffs by configuring
|
||||
// --initial-election-tick-advance at the cost of slow initial bootstrap.
|
||||
//
|
||||
// If single-node, it advances ticks regardless.
|
||||
//
|
||||
// See https://github.com/coreos/etcd/issues/9333 for more detail.
|
||||
InitialElectionTickAdvance bool `json:"initial-election-tick-advance"`
|
||||
|
||||
QuotaBackendBytes int64 `json:"quota-backend-bytes"`
|
||||
MaxRequestBytes uint `json:"max-request-bytes"`
|
||||
|
||||
|
@ -128,6 +160,11 @@ type Config struct {
|
|||
PeerTLSInfo transport.TLSInfo
|
||||
PeerAutoTLS bool
|
||||
|
||||
// CipherSuites is a list of supported TLS cipher suites between
|
||||
// client/server and peers. If empty, Go auto-populates the list.
|
||||
// Note that cipher suites are prioritized in the given order.
|
||||
CipherSuites []string `json:"cipher-suites"`
|
||||
|
||||
// debug
|
||||
|
||||
Debug bool `json:"debug"`
|
||||
|
@ -190,27 +227,28 @@ func NewConfig() *Config {
|
|||
lcurl, _ := url.Parse(DefaultListenClientURLs)
|
||||
acurl, _ := url.Parse(DefaultAdvertiseClientURLs)
|
||||
cfg := &Config{
|
||||
CorsInfo: &cors.CORSInfo{},
|
||||
MaxSnapFiles: DefaultMaxSnapshots,
|
||||
MaxWalFiles: DefaultMaxWALs,
|
||||
Name: DefaultName,
|
||||
SnapCount: etcdserver.DefaultSnapCount,
|
||||
MaxRequestBytes: DefaultMaxRequestBytes,
|
||||
GRPCKeepAliveMinTime: DefaultGRPCKeepAliveMinTime,
|
||||
GRPCKeepAliveInterval: DefaultGRPCKeepAliveInterval,
|
||||
GRPCKeepAliveTimeout: DefaultGRPCKeepAliveTimeout,
|
||||
TickMs: 100,
|
||||
ElectionMs: 1000,
|
||||
LPUrls: []url.URL{*lpurl},
|
||||
LCUrls: []url.URL{*lcurl},
|
||||
APUrls: []url.URL{*apurl},
|
||||
ACUrls: []url.URL{*acurl},
|
||||
ClusterState: ClusterStateFlagNew,
|
||||
InitialClusterToken: "etcd-cluster",
|
||||
StrictReconfigCheck: true,
|
||||
Metrics: "basic",
|
||||
EnableV2: true,
|
||||
AuthToken: "simple",
|
||||
CorsInfo: &cors.CORSInfo{},
|
||||
MaxSnapFiles: DefaultMaxSnapshots,
|
||||
MaxWalFiles: DefaultMaxWALs,
|
||||
Name: DefaultName,
|
||||
SnapCount: etcdserver.DefaultSnapCount,
|
||||
MaxRequestBytes: DefaultMaxRequestBytes,
|
||||
GRPCKeepAliveMinTime: DefaultGRPCKeepAliveMinTime,
|
||||
GRPCKeepAliveInterval: DefaultGRPCKeepAliveInterval,
|
||||
GRPCKeepAliveTimeout: DefaultGRPCKeepAliveTimeout,
|
||||
TickMs: 100,
|
||||
ElectionMs: 1000,
|
||||
InitialElectionTickAdvance: true,
|
||||
LPUrls: []url.URL{*lpurl},
|
||||
LCUrls: []url.URL{*lcurl},
|
||||
APUrls: []url.URL{*apurl},
|
||||
ACUrls: []url.URL{*acurl},
|
||||
ClusterState: ClusterStateFlagNew,
|
||||
InitialClusterToken: "etcd-cluster",
|
||||
StrictReconfigCheck: true,
|
||||
Metrics: "basic",
|
||||
EnableV2: true,
|
||||
AuthToken: "simple",
|
||||
}
|
||||
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
|
||||
return cfg
|
||||
|
@ -298,6 +336,25 @@ func (cfg *configYAML) configFromFile(path string) error {
|
|||
return cfg.Validate()
|
||||
}
|
||||
|
||||
func updateCipherSuites(tls *transport.TLSInfo, ss []string) error {
|
||||
if len(tls.CipherSuites) > 0 && len(ss) > 0 {
|
||||
return fmt.Errorf("TLSInfo.CipherSuites is already specified (given %v)", ss)
|
||||
}
|
||||
if len(ss) > 0 {
|
||||
cs := make([]uint16, len(ss))
|
||||
for i, s := range ss {
|
||||
var ok bool
|
||||
cs[i], ok = tlsutil.GetCipherSuite(s)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected TLS cipher suite %q", s)
|
||||
}
|
||||
}
|
||||
tls.CipherSuites = cs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate ensures that '*embed.Config' fields are properly configured.
|
||||
func (cfg *Config) Validate() error {
|
||||
if err := checkBindURLs(cfg.LPUrls); err != nil {
|
||||
return err
|
||||
|
@ -400,6 +457,44 @@ func (cfg Config) defaultClientHost() bool {
|
|||
return len(cfg.ACUrls) == 1 && cfg.ACUrls[0].String() == DefaultAdvertiseClientURLs
|
||||
}
|
||||
|
||||
func (cfg *Config) ClientSelfCert() (err error) {
|
||||
if !cfg.ClientAutoTLS {
|
||||
return nil
|
||||
}
|
||||
if !cfg.ClientTLSInfo.Empty() {
|
||||
plog.Warningf("ignoring client auto TLS since certs given")
|
||||
return nil
|
||||
}
|
||||
chosts := make([]string, len(cfg.LCUrls))
|
||||
for i, u := range cfg.LCUrls {
|
||||
chosts[i] = u.Host
|
||||
}
|
||||
cfg.ClientTLSInfo, err = transport.SelfCert(filepath.Join(cfg.Dir, "fixtures", "client"), chosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return updateCipherSuites(&cfg.ClientTLSInfo, cfg.CipherSuites)
|
||||
}
|
||||
|
||||
func (cfg *Config) PeerSelfCert() (err error) {
|
||||
if !cfg.PeerAutoTLS {
|
||||
return nil
|
||||
}
|
||||
if !cfg.PeerTLSInfo.Empty() {
|
||||
plog.Warningf("ignoring peer auto TLS since certs given")
|
||||
return nil
|
||||
}
|
||||
phosts := make([]string, len(cfg.LPUrls))
|
||||
for i, u := range cfg.LPUrls {
|
||||
phosts[i] = u.Host
|
||||
}
|
||||
cfg.PeerTLSInfo, err = transport.SelfCert(filepath.Join(cfg.Dir, "fixtures", "peer"), phosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return updateCipherSuites(&cfg.PeerTLSInfo, cfg.CipherSuites)
|
||||
}
|
||||
|
||||
// UpdateDefaultClusterFromName updates cluster advertise URLs with, if available, default host,
|
||||
// if advertise URLs are default values(localhost:2379,2380) AND if listen URL is 0.0.0.0.
|
||||
// e.g. advertise peer URL localhost:2380 or listen peer URL 0.0.0.0:2380
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
defaultLog "log"
|
||||
"net"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -128,30 +127,31 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) {
|
|||
}
|
||||
|
||||
srvcfg := &etcdserver.ServerConfig{
|
||||
Name: cfg.Name,
|
||||
ClientURLs: cfg.ACUrls,
|
||||
PeerURLs: cfg.APUrls,
|
||||
DataDir: cfg.Dir,
|
||||
DedicatedWALDir: cfg.WalDir,
|
||||
SnapCount: cfg.SnapCount,
|
||||
MaxSnapFiles: cfg.MaxSnapFiles,
|
||||
MaxWALFiles: cfg.MaxWalFiles,
|
||||
InitialPeerURLsMap: urlsmap,
|
||||
InitialClusterToken: token,
|
||||
DiscoveryURL: cfg.Durl,
|
||||
DiscoveryProxy: cfg.Dproxy,
|
||||
NewCluster: cfg.IsNewCluster(),
|
||||
ForceNewCluster: cfg.ForceNewCluster,
|
||||
PeerTLSInfo: cfg.PeerTLSInfo,
|
||||
TickMs: cfg.TickMs,
|
||||
ElectionTicks: cfg.ElectionTicks(),
|
||||
AutoCompactionRetention: cfg.AutoCompactionRetention,
|
||||
QuotaBackendBytes: cfg.QuotaBackendBytes,
|
||||
MaxRequestBytes: cfg.MaxRequestBytes,
|
||||
StrictReconfigCheck: cfg.StrictReconfigCheck,
|
||||
ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth,
|
||||
AuthToken: cfg.AuthToken,
|
||||
Debug: cfg.Debug,
|
||||
Name: cfg.Name,
|
||||
ClientURLs: cfg.ACUrls,
|
||||
PeerURLs: cfg.APUrls,
|
||||
DataDir: cfg.Dir,
|
||||
DedicatedWALDir: cfg.WalDir,
|
||||
SnapCount: cfg.SnapCount,
|
||||
MaxSnapFiles: cfg.MaxSnapFiles,
|
||||
MaxWALFiles: cfg.MaxWalFiles,
|
||||
InitialPeerURLsMap: urlsmap,
|
||||
InitialClusterToken: token,
|
||||
DiscoveryURL: cfg.Durl,
|
||||
DiscoveryProxy: cfg.Dproxy,
|
||||
NewCluster: cfg.IsNewCluster(),
|
||||
ForceNewCluster: cfg.ForceNewCluster,
|
||||
PeerTLSInfo: cfg.PeerTLSInfo,
|
||||
TickMs: cfg.TickMs,
|
||||
ElectionTicks: cfg.ElectionTicks(),
|
||||
InitialElectionTickAdvance: cfg.InitialElectionTickAdvance,
|
||||
AutoCompactionRetention: cfg.AutoCompactionRetention,
|
||||
QuotaBackendBytes: cfg.QuotaBackendBytes,
|
||||
MaxRequestBytes: cfg.MaxRequestBytes,
|
||||
StrictReconfigCheck: cfg.StrictReconfigCheck,
|
||||
ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth,
|
||||
AuthToken: cfg.AuthToken,
|
||||
Debug: cfg.Debug,
|
||||
}
|
||||
|
||||
if e.Server, err = etcdserver.NewServer(srvcfg); err != nil {
|
||||
|
@ -263,17 +263,11 @@ func stopServers(ctx context.Context, ss *servers) {
|
|||
func (e *Etcd) Err() <-chan error { return e.errc }
|
||||
|
||||
func startPeerListeners(cfg *Config) (peers []*peerListener, err error) {
|
||||
if cfg.PeerAutoTLS && cfg.PeerTLSInfo.Empty() {
|
||||
phosts := make([]string, len(cfg.LPUrls))
|
||||
for i, u := range cfg.LPUrls {
|
||||
phosts[i] = u.Host
|
||||
}
|
||||
cfg.PeerTLSInfo, err = transport.SelfCert(filepath.Join(cfg.Dir, "fixtures", "peer"), phosts)
|
||||
if err != nil {
|
||||
plog.Fatalf("could not get certs (%v)", err)
|
||||
}
|
||||
} else if cfg.PeerAutoTLS {
|
||||
plog.Warningf("ignoring peer auto TLS since certs given")
|
||||
if err = updateCipherSuites(&cfg.PeerTLSInfo, cfg.CipherSuites); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = cfg.PeerSelfCert(); err != nil {
|
||||
plog.Fatalf("could not get certs (%v)", err)
|
||||
}
|
||||
|
||||
if !cfg.PeerTLSInfo.Empty() {
|
||||
|
@ -358,17 +352,11 @@ func (e *Etcd) servePeers() (err error) {
|
|||
}
|
||||
|
||||
func startClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err error) {
|
||||
if cfg.ClientAutoTLS && cfg.ClientTLSInfo.Empty() {
|
||||
chosts := make([]string, len(cfg.LCUrls))
|
||||
for i, u := range cfg.LCUrls {
|
||||
chosts[i] = u.Host
|
||||
}
|
||||
cfg.ClientTLSInfo, err = transport.SelfCert(filepath.Join(cfg.Dir, "fixtures", "client"), chosts)
|
||||
if err != nil {
|
||||
plog.Fatalf("could not get certs (%v)", err)
|
||||
}
|
||||
} else if cfg.ClientAutoTLS {
|
||||
plog.Warningf("ignoring client auto TLS since certs given")
|
||||
if err = updateCipherSuites(&cfg.ClientTLSInfo, cfg.CipherSuites); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = cfg.ClientSelfCert(); err != nil {
|
||||
plog.Fatalf("could not get certs (%v)", err)
|
||||
}
|
||||
|
||||
if cfg.EnablePprof {
|
||||
|
|
|
@ -61,6 +61,7 @@ go_library(
|
|||
"//vendor/github.com/coreos/go-semver/semver:go_default_library",
|
||||
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
||||
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
||||
"//vendor/github.com/golang/protobuf/proto:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/golang.org/x/net/context:go_default_library",
|
||||
],
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
package v3election
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
|
@ -22,6 +24,10 @@ import (
|
|||
epb "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb"
|
||||
)
|
||||
|
||||
// ErrMissingLeaderKey is returned when election API request
|
||||
// is missing the "leader" field.
|
||||
var ErrMissingLeaderKey = errors.New(`"leader" field must be provided`)
|
||||
|
||||
type electionServer struct {
|
||||
c *clientv3.Client
|
||||
}
|
||||
|
@ -51,6 +57,9 @@ func (es *electionServer) Campaign(ctx context.Context, req *epb.CampaignRequest
|
|||
}
|
||||
|
||||
func (es *electionServer) Proclaim(ctx context.Context, req *epb.ProclaimRequest) (*epb.ProclaimResponse, error) {
|
||||
if req.Leader == nil {
|
||||
return nil, ErrMissingLeaderKey
|
||||
}
|
||||
s, err := es.session(ctx, req.Leader.Lease)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -98,6 +107,9 @@ func (es *electionServer) Leader(ctx context.Context, req *epb.LeaderRequest) (*
|
|||
}
|
||||
|
||||
func (es *electionServer) Resign(ctx context.Context, req *epb.ResignRequest) (*epb.ResignResponse, error) {
|
||||
if req.Leader == nil {
|
||||
return nil, ErrMissingLeaderKey
|
||||
}
|
||||
s, err := es.session(ctx, req.Leader.Lease)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -44,6 +44,7 @@ go_library(
|
|||
"//vendor/google.golang.org/grpc/credentials:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/grpclog:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/metadata:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/status:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -92,7 +92,11 @@ func (ls *LeaseServer) leaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) erro
|
|||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
plog.Debugf("failed to receive lease keepalive request from gRPC stream (%q)", err.Error())
|
||||
if isClientCtxErr(stream.Context().Err(), err) {
|
||||
plog.Debugf("failed to receive lease keepalive request from gRPC stream (%q)", err.Error())
|
||||
} else {
|
||||
plog.Warningf("failed to receive lease keepalive request from gRPC stream (%q)", err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -118,7 +122,11 @@ func (ls *LeaseServer) leaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) erro
|
|||
resp.TTL = ttl
|
||||
err = stream.Send(resp)
|
||||
if err != nil {
|
||||
plog.Debugf("failed to send lease keepalive response to gRPC stream (%q)", err.Error())
|
||||
if isClientCtxErr(stream.Context().Err(), err) {
|
||||
plog.Debugf("failed to send lease keepalive response to gRPC stream (%q)", err.Error())
|
||||
} else {
|
||||
plog.Warningf("failed to send lease keepalive response to gRPC stream (%q)", err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,9 @@ var (
|
|||
ErrGRPCFutureRev = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision")
|
||||
ErrGRPCNoSpace = grpc.Errorf(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded")
|
||||
|
||||
ErrGRPCLeaseNotFound = grpc.Errorf(codes.NotFound, "etcdserver: requested lease not found")
|
||||
ErrGRPCLeaseExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: lease already exists")
|
||||
ErrGRPCLeaseNotFound = grpc.Errorf(codes.NotFound, "etcdserver: requested lease not found")
|
||||
ErrGRPCLeaseExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: lease already exists")
|
||||
ErrGRPCLeaseTTLTooLarge = grpc.Errorf(codes.OutOfRange, "etcdserver: too large lease TTL")
|
||||
|
||||
ErrGRPCMemberExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: member ID already exist")
|
||||
ErrGRPCPeerURLExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: Peer URLs already exists")
|
||||
|
@ -79,8 +80,9 @@ var (
|
|||
grpc.ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev,
|
||||
grpc.ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace,
|
||||
|
||||
grpc.ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound,
|
||||
grpc.ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist,
|
||||
grpc.ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound,
|
||||
grpc.ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist,
|
||||
grpc.ErrorDesc(ErrGRPCLeaseTTLTooLarge): ErrGRPCLeaseTTLTooLarge,
|
||||
|
||||
grpc.ErrorDesc(ErrGRPCMemberExist): ErrGRPCMemberExist,
|
||||
grpc.ErrorDesc(ErrGRPCPeerURLExist): ErrGRPCPeerURLExist,
|
||||
|
@ -126,8 +128,9 @@ var (
|
|||
ErrFutureRev = Error(ErrGRPCFutureRev)
|
||||
ErrNoSpace = Error(ErrGRPCNoSpace)
|
||||
|
||||
ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound)
|
||||
ErrLeaseExist = Error(ErrGRPCLeaseExist)
|
||||
ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound)
|
||||
ErrLeaseExist = Error(ErrGRPCLeaseExist)
|
||||
ErrLeaseTTLTooLarge = Error(ErrGRPCLeaseTTLTooLarge)
|
||||
|
||||
ErrMemberExist = Error(ErrGRPCMemberExist)
|
||||
ErrPeerURLExist = Error(ErrGRPCPeerURLExist)
|
||||
|
|
|
@ -15,14 +15,18 @@
|
|||
package v3rpc
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/etcd/auth"
|
||||
"github.com/coreos/etcd/etcdserver"
|
||||
"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
|
||||
"github.com/coreos/etcd/etcdserver/membership"
|
||||
"github.com/coreos/etcd/lease"
|
||||
"github.com/coreos/etcd/mvcc"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func togRPCError(err error) error {
|
||||
|
@ -68,6 +72,8 @@ func togRPCError(err error) error {
|
|||
return rpctypes.ErrGRPCLeaseNotFound
|
||||
case lease.ErrLeaseExists:
|
||||
return rpctypes.ErrGRPCLeaseExist
|
||||
case lease.ErrLeaseTTLTooLarge:
|
||||
return rpctypes.ErrGRPCLeaseTTLTooLarge
|
||||
|
||||
case auth.ErrRootUserNotExist:
|
||||
return rpctypes.ErrGRPCRootUserNotExist
|
||||
|
@ -101,3 +107,35 @@ func togRPCError(err error) error {
|
|||
return grpc.Errorf(codes.Unknown, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func isClientCtxErr(ctxErr error, err error) bool {
|
||||
if ctxErr != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
ev, ok := status.FromError(err)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
switch ev.Code() {
|
||||
case codes.Canceled, codes.DeadlineExceeded:
|
||||
// client-side context cancel or deadline exceeded
|
||||
// "rpc error: code = Canceled desc = context canceled"
|
||||
// "rpc error: code = DeadlineExceeded desc = context deadline exceeded"
|
||||
return true
|
||||
case codes.Unavailable:
|
||||
msg := ev.Message()
|
||||
// client-side context cancel or deadline exceeded with TLS ("http2.errClientDisconnected")
|
||||
// "rpc error: code = Unavailable desc = client disconnected"
|
||||
if msg == "client disconnected" {
|
||||
return true
|
||||
}
|
||||
// "grpc/transport.ClientTransport.CloseStream" on canceled streams
|
||||
// "rpc error: code = Unavailable desc = stream error: stream ID 21; CANCEL")
|
||||
if strings.HasPrefix(msg, "stream error: ") && strings.HasSuffix(msg, "; CANCEL") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -141,7 +141,11 @@ func (ws *watchServer) Watch(stream pb.Watch_WatchServer) (err error) {
|
|||
// deadlock when calling sws.close().
|
||||
go func() {
|
||||
if rerr := sws.recvLoop(); rerr != nil {
|
||||
plog.Debugf("failed to receive watch request from gRPC stream (%q)", rerr.Error())
|
||||
if isClientCtxErr(stream.Context().Err(), rerr) {
|
||||
plog.Debugf("failed to receive watch request from gRPC stream (%q)", rerr.Error())
|
||||
} else {
|
||||
plog.Warningf("failed to receive watch request from gRPC stream (%q)", rerr.Error())
|
||||
}
|
||||
errc <- rerr
|
||||
}
|
||||
}()
|
||||
|
@ -338,7 +342,11 @@ func (sws *serverWatchStream) sendLoop() {
|
|||
|
||||
mvcc.ReportEventReceived(len(evs))
|
||||
if err := sws.gRPCStream.Send(wr); err != nil {
|
||||
plog.Debugf("failed to send watch response to gRPC stream (%q)", err.Error())
|
||||
if isClientCtxErr(sws.gRPCStream.Context().Err(), err) {
|
||||
plog.Debugf("failed to send watch response to gRPC stream (%q)", err.Error())
|
||||
} else {
|
||||
plog.Warningf("failed to send watch response to gRPC stream (%q)", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -355,7 +363,11 @@ func (sws *serverWatchStream) sendLoop() {
|
|||
}
|
||||
|
||||
if err := sws.gRPCStream.Send(c); err != nil {
|
||||
plog.Debugf("failed to send watch control response to gRPC stream (%q)", err.Error())
|
||||
if isClientCtxErr(sws.gRPCStream.Context().Err(), err) {
|
||||
plog.Debugf("failed to send watch control response to gRPC stream (%q)", err.Error())
|
||||
} else {
|
||||
plog.Warningf("failed to send watch control response to gRPC stream (%q)", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -371,7 +383,11 @@ func (sws *serverWatchStream) sendLoop() {
|
|||
for _, v := range pending[wid] {
|
||||
mvcc.ReportEventReceived(len(v.Events))
|
||||
if err := sws.gRPCStream.Send(v); err != nil {
|
||||
plog.Debugf("failed to send pending watch response to gRPC stream (%q)", err.Error())
|
||||
if isClientCtxErr(sws.gRPCStream.Context().Err(), err) {
|
||||
plog.Debugf("failed to send pending watch response to gRPC stream (%q)", err.Error())
|
||||
} else {
|
||||
plog.Warningf("failed to send pending watch response to gRPC stream (%q)", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,9 @@ func (s *EtcdServer) newApplierV3() applierV3 {
|
|||
|
||||
func (a *applierV3backend) Apply(r *pb.InternalRaftRequest) *applyResult {
|
||||
ar := &applyResult{}
|
||||
defer func(start time.Time) {
|
||||
warnOfExpensiveRequest(start, &pb.InternalRaftStringer{Request: r}, ar.resp, ar.err)
|
||||
}(time.Now())
|
||||
|
||||
// call into a.s.applyV3.F instead of a.F so upper appliers can check individual calls
|
||||
switch {
|
||||
|
|
|
@ -105,10 +105,12 @@ func (a *applierV2store) Sync(r *pb.Request) Response {
|
|||
return Response{}
|
||||
}
|
||||
|
||||
// applyV2Request interprets r as a call to store.X and returns a Response interpreted
|
||||
// from store.Event
|
||||
// applyV2Request interprets r as a call to v2store.X
|
||||
// and returns a Response interpreted from v2store.Event
|
||||
func (s *EtcdServer) applyV2Request(r *pb.Request) Response {
|
||||
defer warnOfExpensiveRequest(time.Now(), r, nil, nil)
|
||||
toTTLOptions(r)
|
||||
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
return s.applyV2.Post(r)
|
||||
|
|
|
@ -48,8 +48,38 @@ type ServerConfig struct {
|
|||
ForceNewCluster bool
|
||||
PeerTLSInfo transport.TLSInfo
|
||||
|
||||
TickMs uint
|
||||
ElectionTicks int
|
||||
TickMs uint
|
||||
ElectionTicks int
|
||||
|
||||
// InitialElectionTickAdvance is true, then local member fast-forwards
|
||||
// election ticks to speed up "initial" leader election trigger. This
|
||||
// benefits the case of larger election ticks. For instance, cross
|
||||
// datacenter deployment may require longer election timeout of 10-second.
|
||||
// If true, local node does not need wait up to 10-second. Instead,
|
||||
// forwards its election ticks to 8-second, and have only 2-second left
|
||||
// before leader election.
|
||||
//
|
||||
// Major assumptions are that:
|
||||
// - cluster has no active leader thus advancing ticks enables faster
|
||||
// leader election, or
|
||||
// - cluster already has an established leader, and rejoining follower
|
||||
// is likely to receive heartbeats from the leader after tick advance
|
||||
// and before election timeout.
|
||||
//
|
||||
// However, when network from leader to rejoining follower is congested,
|
||||
// and the follower does not receive leader heartbeat within left election
|
||||
// ticks, disruptive election has to happen thus affecting cluster
|
||||
// availabilities.
|
||||
//
|
||||
// Disabling this would slow down initial bootstrap process for cross
|
||||
// datacenter deployments. Make your own tradeoffs by configuring
|
||||
// --initial-election-tick-advance at the cost of slow initial bootstrap.
|
||||
//
|
||||
// If single-node, it advances ticks regardless.
|
||||
//
|
||||
// See https://github.com/coreos/etcd/issues/9333 for more detail.
|
||||
InitialElectionTickAdvance bool
|
||||
|
||||
BootstrapTimeout time.Duration
|
||||
|
||||
AutoCompactionRetention int
|
||||
|
|
|
@ -5,6 +5,7 @@ go_library(
|
|||
srcs = [
|
||||
"etcdserver.pb.go",
|
||||
"raft_internal.pb.go",
|
||||
"raft_internal_stringer.go",
|
||||
"rpc.pb.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||
|
|
179
vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
generated
vendored
Normal file
179
vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
generated
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package etcdserverpb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// InternalRaftStringer implements custom proto Stringer:
|
||||
// redact password, replace value fields with value_size fields.
|
||||
type InternalRaftStringer struct {
|
||||
Request *InternalRaftRequest
|
||||
}
|
||||
|
||||
func (as *InternalRaftStringer) String() string {
|
||||
switch {
|
||||
case as.Request.LeaseGrant != nil:
|
||||
return fmt.Sprintf("header:<%s> lease_grant:<ttl:%d-second id:%016x>",
|
||||
as.Request.Header.String(),
|
||||
as.Request.LeaseGrant.TTL,
|
||||
as.Request.LeaseGrant.ID,
|
||||
)
|
||||
case as.Request.LeaseRevoke != nil:
|
||||
return fmt.Sprintf("header:<%s> lease_revoke:<id:%016x>",
|
||||
as.Request.Header.String(),
|
||||
as.Request.LeaseRevoke.ID,
|
||||
)
|
||||
case as.Request.Authenticate != nil:
|
||||
return fmt.Sprintf("header:<%s> authenticate:<name:%s simple_token:%s>",
|
||||
as.Request.Header.String(),
|
||||
as.Request.Authenticate.Name,
|
||||
as.Request.Authenticate.SimpleToken,
|
||||
)
|
||||
case as.Request.AuthUserAdd != nil:
|
||||
return fmt.Sprintf("header:<%s> auth_user_add:<name:%s>",
|
||||
as.Request.Header.String(),
|
||||
as.Request.AuthUserAdd.Name,
|
||||
)
|
||||
case as.Request.AuthUserChangePassword != nil:
|
||||
return fmt.Sprintf("header:<%s> auth_user_change_password:<name:%s>",
|
||||
as.Request.Header.String(),
|
||||
as.Request.AuthUserChangePassword.Name,
|
||||
)
|
||||
case as.Request.Put != nil:
|
||||
return fmt.Sprintf("header:<%s> put:<%s>",
|
||||
as.Request.Header.String(),
|
||||
newLoggablePutRequest(as.Request.Put).String(),
|
||||
)
|
||||
case as.Request.Txn != nil:
|
||||
return fmt.Sprintf("header:<%s> txn:<%s>",
|
||||
as.Request.Header.String(),
|
||||
NewLoggableTxnRequest(as.Request.Txn).String(),
|
||||
)
|
||||
default:
|
||||
// nothing to redact
|
||||
}
|
||||
return as.Request.String()
|
||||
}
|
||||
|
||||
// txnRequestStringer implements a custom proto String to replace value bytes fields with value size
|
||||
// fields in any nested txn and put operations.
|
||||
type txnRequestStringer struct {
|
||||
Request *TxnRequest
|
||||
}
|
||||
|
||||
func NewLoggableTxnRequest(request *TxnRequest) *txnRequestStringer {
|
||||
return &txnRequestStringer{request}
|
||||
}
|
||||
|
||||
func (as *txnRequestStringer) String() string {
|
||||
var compare []string
|
||||
for _, c := range as.Request.Compare {
|
||||
switch cv := c.TargetUnion.(type) {
|
||||
case *Compare_Value:
|
||||
compare = append(compare, newLoggableValueCompare(c, cv).String())
|
||||
default:
|
||||
// nothing to redact
|
||||
compare = append(compare, c.String())
|
||||
}
|
||||
}
|
||||
var success []string
|
||||
for _, s := range as.Request.Success {
|
||||
success = append(success, newLoggableRequestOp(s).String())
|
||||
}
|
||||
var failure []string
|
||||
for _, f := range as.Request.Failure {
|
||||
failure = append(failure, newLoggableRequestOp(f).String())
|
||||
}
|
||||
return fmt.Sprintf("compare:<%s> success:<%s> failure:<%s>",
|
||||
strings.Join(compare, " "),
|
||||
strings.Join(success, " "),
|
||||
strings.Join(failure, " "),
|
||||
)
|
||||
}
|
||||
|
||||
// requestOpStringer implements a custom proto String to replace value bytes fields with value
|
||||
// size fields in any nested txn and put operations.
|
||||
type requestOpStringer struct {
|
||||
Op *RequestOp
|
||||
}
|
||||
|
||||
func newLoggableRequestOp(op *RequestOp) *requestOpStringer {
|
||||
return &requestOpStringer{op}
|
||||
}
|
||||
|
||||
func (as *requestOpStringer) String() string {
|
||||
switch op := as.Op.Request.(type) {
|
||||
case *RequestOp_RequestPut:
|
||||
return fmt.Sprintf("request_put:<%s>", newLoggablePutRequest(op.RequestPut).String())
|
||||
default:
|
||||
// nothing to redact
|
||||
}
|
||||
return as.Op.String()
|
||||
}
|
||||
|
||||
// loggableValueCompare implements a custom proto String for Compare.Value union member types to
|
||||
// replace the value bytes field with a value size field.
|
||||
// To preserve proto encoding of the key and range_end bytes, a faked out proto type is used here.
|
||||
type loggableValueCompare struct {
|
||||
Result Compare_CompareResult `protobuf:"varint,1,opt,name=result,proto3,enum=etcdserverpb.Compare_CompareResult"`
|
||||
Target Compare_CompareTarget `protobuf:"varint,2,opt,name=target,proto3,enum=etcdserverpb.Compare_CompareTarget"`
|
||||
Key []byte `protobuf:"bytes,3,opt,name=key,proto3"`
|
||||
ValueSize int `protobuf:"bytes,7,opt,name=value_size,proto3"`
|
||||
}
|
||||
|
||||
func newLoggableValueCompare(c *Compare, cv *Compare_Value) *loggableValueCompare {
|
||||
return &loggableValueCompare{
|
||||
c.Result,
|
||||
c.Target,
|
||||
c.Key,
|
||||
len(cv.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *loggableValueCompare) Reset() { *m = loggableValueCompare{} }
|
||||
func (m *loggableValueCompare) String() string { return proto.CompactTextString(m) }
|
||||
func (*loggableValueCompare) ProtoMessage() {}
|
||||
|
||||
// loggablePutRequest implements a custom proto String to replace value bytes field with a value
|
||||
// size field.
|
||||
// To preserve proto encoding of the key bytes, a faked out proto type is used here.
|
||||
type loggablePutRequest struct {
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3"`
|
||||
ValueSize int `protobuf:"varint,2,opt,name=value_size,proto3"`
|
||||
Lease int64 `protobuf:"varint,3,opt,name=lease,proto3"`
|
||||
PrevKv bool `protobuf:"varint,4,opt,name=prev_kv,proto3"`
|
||||
IgnoreValue bool `protobuf:"varint,5,opt,name=ignore_value,proto3"`
|
||||
IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,proto3"`
|
||||
}
|
||||
|
||||
func newLoggablePutRequest(request *PutRequest) *loggablePutRequest {
|
||||
return &loggablePutRequest{
|
||||
request.Key,
|
||||
len(request.Value),
|
||||
request.Lease,
|
||||
request.PrevKv,
|
||||
request.IgnoreValue,
|
||||
request.IgnoreLease,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *loggablePutRequest) Reset() { *m = loggablePutRequest{} }
|
||||
func (m *loggablePutRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*loggablePutRequest) ProtoMessage() {}
|
|
@ -15,9 +15,11 @@
|
|||
package etcdserver
|
||||
|
||||
import (
|
||||
goruntime "runtime"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/pkg/runtime"
|
||||
"github.com/coreos/etcd/version"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -28,12 +30,30 @@ var (
|
|||
Name: "has_leader",
|
||||
Help: "Whether or not a leader exists. 1 is existence, 0 is not.",
|
||||
})
|
||||
isLeader = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "is_leader",
|
||||
Help: "Whether or not this member is a leader. 1 if is, 0 otherwise.",
|
||||
})
|
||||
leaderChanges = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "leader_changes_seen_total",
|
||||
Help: "The number of leader changes seen.",
|
||||
})
|
||||
heartbeatSendFailures = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "heartbeat_send_failures_total",
|
||||
Help: "The total number of leader heartbeat send failures (likely overloaded from slow disk).",
|
||||
})
|
||||
slowApplies = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "slow_apply_total",
|
||||
Help: "The total number of slow apply requests (likely overloaded from slow disk).",
|
||||
})
|
||||
proposalsCommitted = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
|
@ -64,16 +84,56 @@ var (
|
|||
Name: "lease_expired_total",
|
||||
Help: "The total number of expired leases.",
|
||||
})
|
||||
slowReadIndex = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "slow_read_indexes_total",
|
||||
Help: "The total number of pending read indexes not in sync with leader's or timed out read index requests.",
|
||||
})
|
||||
quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "quota_backend_bytes",
|
||||
Help: "Current backend storage quota size in bytes.",
|
||||
})
|
||||
currentVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "version",
|
||||
Help: "Which version is running. 1 for 'server_version' label with current version.",
|
||||
},
|
||||
[]string{"server_version"})
|
||||
currentGoVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "go_version",
|
||||
Help: "Which Go version server is running with. 1 for 'server_go_version' label with current version.",
|
||||
},
|
||||
[]string{"server_go_version"})
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(hasLeader)
|
||||
prometheus.MustRegister(isLeader)
|
||||
prometheus.MustRegister(leaderChanges)
|
||||
prometheus.MustRegister(heartbeatSendFailures)
|
||||
prometheus.MustRegister(slowApplies)
|
||||
prometheus.MustRegister(proposalsCommitted)
|
||||
prometheus.MustRegister(proposalsApplied)
|
||||
prometheus.MustRegister(proposalsPending)
|
||||
prometheus.MustRegister(proposalsFailed)
|
||||
prometheus.MustRegister(leaseExpired)
|
||||
prometheus.MustRegister(slowReadIndex)
|
||||
prometheus.MustRegister(quotaBackendBytes)
|
||||
prometheus.MustRegister(currentVersion)
|
||||
prometheus.MustRegister(currentGoVersion)
|
||||
|
||||
currentVersion.With(prometheus.Labels{
|
||||
"server_version": version.Version,
|
||||
}).Set(1)
|
||||
currentGoVersion.With(prometheus.Labels{
|
||||
"server_go_version": goruntime.Version(),
|
||||
}).Set(1)
|
||||
}
|
||||
|
||||
func monitorFileDescriptor(done <-chan struct{}) {
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
|
||||
package etcdserver
|
||||
|
||||
import (
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
)
|
||||
import pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
|
||||
const (
|
||||
// DefaultQuotaBytes is the number of bytes the backend Size may
|
||||
|
@ -58,15 +56,20 @@ const (
|
|||
)
|
||||
|
||||
func NewBackendQuota(s *EtcdServer) Quota {
|
||||
quotaBackendBytes.Set(float64(s.Cfg.QuotaBackendBytes))
|
||||
|
||||
if s.Cfg.QuotaBackendBytes < 0 {
|
||||
// disable quotas if negative
|
||||
plog.Warningf("disabling backend quota")
|
||||
return &passthroughQuota{}
|
||||
}
|
||||
|
||||
if s.Cfg.QuotaBackendBytes == 0 {
|
||||
// use default size if no quota size given
|
||||
quotaBackendBytes.Set(float64(DefaultQuotaBytes))
|
||||
return &backendQuota{s, DefaultQuotaBytes}
|
||||
}
|
||||
|
||||
if s.Cfg.QuotaBackendBytes > MaxQuotaBytes {
|
||||
plog.Warningf("backend quota %v exceeds maximum recommended quota %v", s.Cfg.QuotaBackendBytes, MaxQuotaBytes)
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ type raftNode struct {
|
|||
term uint64
|
||||
lead uint64
|
||||
|
||||
tickMu *sync.Mutex
|
||||
raftNodeConfig
|
||||
|
||||
// a chan to send/receive snapshot
|
||||
|
@ -131,6 +132,7 @@ type raftNodeConfig struct {
|
|||
|
||||
func newRaftNode(cfg raftNodeConfig) *raftNode {
|
||||
r := &raftNode{
|
||||
tickMu: new(sync.Mutex),
|
||||
raftNodeConfig: cfg,
|
||||
// set up contention detectors for raft heartbeat message.
|
||||
// expect to send a heartbeat within 2 heartbeat intervals.
|
||||
|
@ -149,6 +151,13 @@ func newRaftNode(cfg raftNodeConfig) *raftNode {
|
|||
return r
|
||||
}
|
||||
|
||||
// raft.Node does not have locks in Raft package
|
||||
func (r *raftNode) tick() {
|
||||
r.tickMu.Lock()
|
||||
r.Tick()
|
||||
r.tickMu.Unlock()
|
||||
}
|
||||
|
||||
// start prepares and starts raftNode in a new goroutine. It is no longer safe
|
||||
// to modify the fields after it has been started.
|
||||
func (r *raftNode) start(rh *raftReadyHandler) {
|
||||
|
@ -161,7 +170,7 @@ func (r *raftNode) start(rh *raftReadyHandler) {
|
|||
for {
|
||||
select {
|
||||
case <-r.ticker.C:
|
||||
r.Tick()
|
||||
r.tick()
|
||||
case rd := <-r.Ready():
|
||||
if rd.SoftState != nil {
|
||||
newLeader := rd.SoftState.Lead != raft.None && atomic.LoadUint64(&r.lead) != rd.SoftState.Lead
|
||||
|
@ -177,6 +186,11 @@ func (r *raftNode) start(rh *raftReadyHandler) {
|
|||
|
||||
atomic.StoreUint64(&r.lead, rd.SoftState.Lead)
|
||||
islead = rd.RaftState == raft.StateLeader
|
||||
if islead {
|
||||
isLeader.Set(1)
|
||||
} else {
|
||||
isLeader.Set(0)
|
||||
}
|
||||
rh.updateLeadership(newLeader)
|
||||
r.td.Reset()
|
||||
}
|
||||
|
@ -332,6 +346,7 @@ func (r *raftNode) processMessages(ms []raftpb.Message) []raftpb.Message {
|
|||
// TODO: limit request rate.
|
||||
plog.Warningf("failed to send out heartbeat on time (exceeded the %v timeout for %v)", r.heartbeat, exceed)
|
||||
plog.Warningf("server is likely overloaded")
|
||||
heartbeatSendFailures.Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,13 +383,13 @@ func (r *raftNode) resumeSending() {
|
|||
p.Resume()
|
||||
}
|
||||
|
||||
// advanceTicksForElection advances ticks to the node for fast election.
|
||||
// This reduces the time to wait for first leader election if bootstrapping the whole
|
||||
// cluster, while leaving at least 1 heartbeat for possible existing leader
|
||||
// to contact it.
|
||||
func advanceTicksForElection(n raft.Node, electionTicks int) {
|
||||
for i := 0; i < electionTicks-1; i++ {
|
||||
n.Tick()
|
||||
// advanceTicks advances ticks of Raft node.
|
||||
// This can be used for fast-forwarding election
|
||||
// ticks in multi data-center deployments, thus
|
||||
// speeding up election process.
|
||||
func (r *raftNode) advanceTicks(ticks int) {
|
||||
for i := 0; i < ticks; i++ {
|
||||
r.tick()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,8 +430,8 @@ func startNode(cfg *ServerConfig, cl *membership.RaftCluster, ids []types.ID) (i
|
|||
raftStatusMu.Lock()
|
||||
raftStatus = n.Status
|
||||
raftStatusMu.Unlock()
|
||||
advanceTicksForElection(n, c.ElectionTick)
|
||||
return
|
||||
|
||||
return id, n, s, w
|
||||
}
|
||||
|
||||
func restartNode(cfg *ServerConfig, snapshot *raftpb.Snapshot) (types.ID, *membership.RaftCluster, raft.Node, *raft.MemoryStorage, *wal.WAL) {
|
||||
|
@ -449,7 +464,6 @@ func restartNode(cfg *ServerConfig, snapshot *raftpb.Snapshot) (types.ID, *membe
|
|||
raftStatusMu.Lock()
|
||||
raftStatus = n.Status
|
||||
raftStatusMu.Unlock()
|
||||
advanceTicksForElection(n, c.ElectionTick)
|
||||
return id, cl, n, s, w
|
||||
}
|
||||
|
||||
|
@ -498,6 +512,7 @@ func restartAsStandaloneNode(cfg *ServerConfig, snapshot *raftpb.Snapshot) (type
|
|||
Storage: s,
|
||||
MaxSizePerMsg: maxSizePerMsg,
|
||||
MaxInflightMsgs: maxInflightMsgs,
|
||||
CheckQuorum: true,
|
||||
}
|
||||
n := raft.RestartNode(c)
|
||||
raftStatus = n.Status
|
||||
|
|
|
@ -513,11 +513,56 @@ func NewServer(cfg *ServerConfig) (srv *EtcdServer, err error) {
|
|||
return srv, nil
|
||||
}
|
||||
|
||||
// Start prepares and starts server in a new goroutine. It is no longer safe to
|
||||
// modify a server's fields after it has been sent to Start.
|
||||
// It also starts a goroutine to publish its server information.
|
||||
func (s *EtcdServer) adjustTicks() {
|
||||
clusterN := len(s.cluster.Members())
|
||||
|
||||
// single-node fresh start, or single-node recovers from snapshot
|
||||
if clusterN == 1 {
|
||||
ticks := s.Cfg.ElectionTicks - 1
|
||||
plog.Infof("%s as single-node; fast-forwarding %d ticks (election ticks %d)", s.ID(), ticks, s.Cfg.ElectionTicks)
|
||||
s.r.advanceTicks(ticks)
|
||||
return
|
||||
}
|
||||
|
||||
if !s.Cfg.InitialElectionTickAdvance {
|
||||
plog.Infof("skipping initial election tick advance (election tick %d)", s.Cfg.ElectionTicks)
|
||||
return
|
||||
}
|
||||
|
||||
// retry up to "rafthttp.ConnReadTimeout", which is 5-sec
|
||||
// until peer connection reports; otherwise:
|
||||
// 1. all connections failed, or
|
||||
// 2. no active peers, or
|
||||
// 3. restarted single-node with no snapshot
|
||||
// then, do nothing, because advancing ticks would have no effect
|
||||
waitTime := rafthttp.ConnReadTimeout
|
||||
itv := 50 * time.Millisecond
|
||||
for i := int64(0); i < int64(waitTime/itv); i++ {
|
||||
select {
|
||||
case <-time.After(itv):
|
||||
case <-s.stopping:
|
||||
return
|
||||
}
|
||||
|
||||
peerN := s.r.transport.ActivePeers()
|
||||
if peerN > 1 {
|
||||
// multi-node received peer connection reports
|
||||
// adjust ticks, in case slow leader message receive
|
||||
ticks := s.Cfg.ElectionTicks - 2
|
||||
plog.Infof("%s initialzed peer connection; fast-forwarding %d ticks (election ticks %d) with %d active peer(s)", s.ID(), ticks, s.Cfg.ElectionTicks, peerN)
|
||||
s.r.advanceTicks(ticks)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start performs any initialization of the Server necessary for it to
|
||||
// begin serving requests. It must be called before Do or Process.
|
||||
// Start must be non-blocking; any long-running server functionality
|
||||
// should be implemented in goroutines.
|
||||
func (s *EtcdServer) Start() {
|
||||
s.start()
|
||||
s.goAttach(func() { s.adjustTicks() })
|
||||
s.goAttach(func() { s.publish(s.Cfg.ReqTimeout()) })
|
||||
s.goAttach(s.purgeFile)
|
||||
s.goAttach(func() { monitorFileDescriptor(s.stopping) })
|
||||
|
@ -552,18 +597,21 @@ func (s *EtcdServer) start() {
|
|||
}
|
||||
|
||||
func (s *EtcdServer) purgeFile() {
|
||||
var serrc, werrc <-chan error
|
||||
var dberrc, serrc, werrc <-chan error
|
||||
if s.Cfg.MaxSnapFiles > 0 {
|
||||
dberrc = fileutil.PurgeFile(s.Cfg.SnapDir(), "snap.db", s.Cfg.MaxSnapFiles, purgeFileInterval, s.done)
|
||||
serrc = fileutil.PurgeFile(s.Cfg.SnapDir(), "snap", s.Cfg.MaxSnapFiles, purgeFileInterval, s.done)
|
||||
}
|
||||
if s.Cfg.MaxWALFiles > 0 {
|
||||
werrc = fileutil.PurgeFile(s.Cfg.WALDir(), "wal", s.Cfg.MaxWALFiles, purgeFileInterval, s.done)
|
||||
}
|
||||
select {
|
||||
case e := <-werrc:
|
||||
plog.Fatalf("failed to purge wal file %v", e)
|
||||
case e := <-dberrc:
|
||||
plog.Fatalf("failed to purge snap db file %v", e)
|
||||
case e := <-serrc:
|
||||
plog.Fatalf("failed to purge snap file %v", e)
|
||||
case e := <-werrc:
|
||||
plog.Fatalf("failed to purge wal file %v", e)
|
||||
case <-s.stopping:
|
||||
return
|
||||
}
|
||||
|
@ -743,8 +791,13 @@ func (s *EtcdServer) run() {
|
|||
}
|
||||
lid := lease.ID
|
||||
s.goAttach(func() {
|
||||
s.LeaseRevoke(s.ctx, &pb.LeaseRevokeRequest{ID: int64(lid)})
|
||||
leaseExpired.Inc()
|
||||
_, lerr := s.LeaseRevoke(s.ctx, &pb.LeaseRevokeRequest{ID: int64(lid)})
|
||||
if lerr == nil {
|
||||
leaseExpired.Inc()
|
||||
} else {
|
||||
plog.Warningf("failed to revoke %016x (%q)", lid, lerr.Error())
|
||||
}
|
||||
|
||||
<-c
|
||||
})
|
||||
}
|
||||
|
@ -765,14 +818,8 @@ func (s *EtcdServer) run() {
|
|||
|
||||
func (s *EtcdServer) applyAll(ep *etcdProgress, apply *apply) {
|
||||
s.applySnapshot(ep, apply)
|
||||
st := time.Now()
|
||||
s.applyEntries(ep, apply)
|
||||
d := time.Since(st)
|
||||
entriesNum := len(apply.entries)
|
||||
if entriesNum != 0 && d > time.Duration(entriesNum)*warnApplyDuration {
|
||||
plog.Warningf("apply entries took too long [%v for %d entries]", d, len(apply.entries))
|
||||
plog.Warningf("avoid queries with large range/delete range!")
|
||||
}
|
||||
|
||||
proposalsApplied.Set(float64(ep.appliedi))
|
||||
s.applyWait.Trigger(ep.appliedi)
|
||||
// wait for the raft routine to finish the disk writes before triggering a
|
||||
|
|
|
@ -74,10 +74,10 @@ type serverStats struct {
|
|||
func (ss *ServerStats) JSON() []byte {
|
||||
ss.Lock()
|
||||
stats := ss.serverStats
|
||||
ss.Unlock()
|
||||
stats.LeaderInfo.Uptime = time.Since(stats.LeaderInfo.StartTime).String()
|
||||
stats.SendingPkgRate, stats.SendingBandwidthRate = stats.sendRateQueue.Rate()
|
||||
stats.RecvingPkgRate, stats.RecvingBandwidthRate = stats.recvRateQueue.Rate()
|
||||
stats.LeaderInfo.Uptime = time.Since(stats.LeaderInfo.StartTime).String()
|
||||
ss.Unlock()
|
||||
b, err := json.Marshal(stats)
|
||||
// TODO(jonboulle): appropriate error handling?
|
||||
if err != nil {
|
||||
|
|
|
@ -15,11 +15,16 @@
|
|||
package etcdserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
"github.com/coreos/etcd/etcdserver/membership"
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
"github.com/coreos/etcd/rafthttp"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// isConnectedToQuorumSince checks whether the local member is connected to the
|
||||
|
@ -95,3 +100,56 @@ func (nc *notifier) notify(err error) {
|
|||
nc.err = err
|
||||
close(nc.c)
|
||||
}
|
||||
|
||||
func warnOfExpensiveRequest(now time.Time, reqStringer fmt.Stringer, respMsg proto.Message, err error) {
|
||||
var resp string
|
||||
if !isNil(respMsg) {
|
||||
resp = fmt.Sprintf("size:%d", proto.Size(respMsg))
|
||||
}
|
||||
warnOfExpensiveGenericRequest(now, reqStringer, "", resp, err)
|
||||
}
|
||||
|
||||
func warnOfExpensiveReadOnlyTxnRequest(now time.Time, r *pb.TxnRequest, txnResponse *pb.TxnResponse, err error) {
|
||||
reqStringer := pb.NewLoggableTxnRequest(r)
|
||||
var resp string
|
||||
if !isNil(txnResponse) {
|
||||
var resps []string
|
||||
for _, r := range txnResponse.Responses {
|
||||
switch op := r.Response.(type) {
|
||||
case *pb.ResponseOp_ResponseRange:
|
||||
resps = append(resps, fmt.Sprintf("range_response_count:%d", len(op.ResponseRange.Kvs)))
|
||||
default:
|
||||
// only range responses should be in a read only txn request
|
||||
}
|
||||
}
|
||||
resp = fmt.Sprintf("responses:<%s> size:%d", strings.Join(resps, " "), proto.Size(txnResponse))
|
||||
}
|
||||
warnOfExpensiveGenericRequest(now, reqStringer, "read-only range ", resp, err)
|
||||
}
|
||||
|
||||
func warnOfExpensiveReadOnlyRangeRequest(now time.Time, reqStringer fmt.Stringer, rangeResponse *pb.RangeResponse, err error) {
|
||||
var resp string
|
||||
if !isNil(rangeResponse) {
|
||||
resp = fmt.Sprintf("range_response_count:%d size:%d", len(rangeResponse.Kvs), proto.Size(rangeResponse))
|
||||
}
|
||||
warnOfExpensiveGenericRequest(now, reqStringer, "read-only range ", resp, err)
|
||||
}
|
||||
|
||||
func warnOfExpensiveGenericRequest(now time.Time, reqStringer fmt.Stringer, prefix string, resp string, err error) {
|
||||
// TODO: add metrics
|
||||
d := time.Since(now)
|
||||
if d > warnApplyDuration {
|
||||
var result string
|
||||
if err != nil {
|
||||
result = fmt.Sprintf("error:%v", err)
|
||||
} else {
|
||||
result = resp
|
||||
}
|
||||
plog.Warningf("%srequest %q with result %q took too long (%v) to execute", prefix, reqStringer.String(), result, d)
|
||||
slowApplies.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func isNil(msg proto.Message) bool {
|
||||
return msg == nil || reflect.ValueOf(msg).IsNil()
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ import (
|
|||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
"github.com/coreos/etcd/auth"
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
"github.com/coreos/etcd/etcdserver/membership"
|
||||
|
@ -28,7 +26,7 @@ import (
|
|||
"github.com/coreos/etcd/lease/leasehttp"
|
||||
"github.com/coreos/etcd/mvcc"
|
||||
"github.com/coreos/etcd/raft"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
@ -82,20 +80,26 @@ type Authenticator interface {
|
|||
}
|
||||
|
||||
func (s *EtcdServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
|
||||
var resp *pb.RangeResponse
|
||||
var err error
|
||||
defer func(start time.Time) {
|
||||
warnOfExpensiveReadOnlyRangeRequest(start, r, resp, err)
|
||||
}(time.Now())
|
||||
|
||||
if !r.Serializable {
|
||||
err := s.linearizableReadNotify(ctx)
|
||||
err = s.linearizableReadNotify(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var resp *pb.RangeResponse
|
||||
var err error
|
||||
chk := func(ai *auth.AuthInfo) error {
|
||||
return s.authStore.IsRangePermitted(ai, r.Key, r.RangeEnd)
|
||||
}
|
||||
|
||||
get := func() { resp, err = s.applyV3Base.Range(nil, r) }
|
||||
if serr := s.doSerialize(ctx, chk, get); serr != nil {
|
||||
return nil, serr
|
||||
err = serr
|
||||
return nil, err
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
@ -129,12 +133,18 @@ func (s *EtcdServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse
|
|||
chk := func(ai *auth.AuthInfo) error {
|
||||
return checkTxnAuth(s.authStore, ai, r)
|
||||
}
|
||||
|
||||
defer func(start time.Time) {
|
||||
warnOfExpensiveReadOnlyTxnRequest(start, r, resp, err)
|
||||
}(time.Now())
|
||||
|
||||
get := func() { resp, err = s.applyV3Base.Txn(r) }
|
||||
if serr := s.doSerialize(ctx, chk, get); serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{Txn: r})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -587,8 +597,9 @@ func (s *EtcdServer) linearizableReadLoop() {
|
|||
var rs raft.ReadState
|
||||
|
||||
for {
|
||||
ctx := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(ctx, s.reqIDGen.Next())
|
||||
ctxToSend := make([]byte, 8)
|
||||
id1 := s.reqIDGen.Next()
|
||||
binary.BigEndian.PutUint64(ctxToSend, id1)
|
||||
|
||||
select {
|
||||
case <-s.readwaitc:
|
||||
|
@ -604,7 +615,7 @@ func (s *EtcdServer) linearizableReadLoop() {
|
|||
s.readMu.Unlock()
|
||||
|
||||
cctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout())
|
||||
if err := s.r.ReadIndex(cctx, ctx); err != nil {
|
||||
if err := s.r.ReadIndex(cctx, ctxToSend); err != nil {
|
||||
cancel()
|
||||
if err == raft.ErrStopped {
|
||||
return
|
||||
|
@ -622,16 +633,24 @@ func (s *EtcdServer) linearizableReadLoop() {
|
|||
for !timeout && !done {
|
||||
select {
|
||||
case rs = <-s.r.readStateC:
|
||||
done = bytes.Equal(rs.RequestCtx, ctx)
|
||||
done = bytes.Equal(rs.RequestCtx, ctxToSend)
|
||||
if !done {
|
||||
// a previous request might time out. now we should ignore the response of it and
|
||||
// continue waiting for the response of the current requests.
|
||||
plog.Warningf("ignored out-of-date read index response (want %v, got %v)", rs.RequestCtx, ctx)
|
||||
id2 := uint64(0)
|
||||
if len(rs.RequestCtx) == 8 {
|
||||
id2 = binary.BigEndian.Uint64(rs.RequestCtx)
|
||||
}
|
||||
plog.Warningf("ignored out-of-date read index response; local node read indexes queueing up and waiting to be in sync with leader (request ID want %d, got %d)", id1, id2)
|
||||
slowReadIndex.Inc()
|
||||
}
|
||||
|
||||
case <-time.After(s.Cfg.ReqTimeout()):
|
||||
plog.Warningf("timed out waiting for read index response")
|
||||
nr.notify(ErrTimeout)
|
||||
timeout = true
|
||||
slowReadIndex.Inc()
|
||||
|
||||
case <-s.stopping:
|
||||
return
|
||||
}
|
||||
|
@ -681,6 +700,5 @@ func (s *EtcdServer) AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error
|
|||
return authInfo, nil
|
||||
}
|
||||
}
|
||||
|
||||
return s.AuthStore().AuthInfoFromCtx(ctx)
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ go_library(
|
|||
"//vendor/github.com/coreos/etcd/etcdserver/api/v3rpc:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/etcdserver/etcdserverpb:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/testutil:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/tlsutil:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/transport:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/pkg/types:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/rafthttp:go_default_library",
|
||||
|
|
|
@ -45,6 +45,7 @@ import (
|
|||
"github.com/coreos/etcd/etcdserver/api/v3rpc"
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
"github.com/coreos/etcd/pkg/testutil"
|
||||
"github.com/coreos/etcd/pkg/tlsutil"
|
||||
"github.com/coreos/etcd/pkg/transport"
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
"github.com/coreos/etcd/rafthttp"
|
||||
|
@ -562,6 +563,7 @@ func mustNewMember(t *testing.T, mcfg memberConfig) *member {
|
|||
m.ServerConfig.PeerTLSInfo = *m.PeerTLSInfo
|
||||
}
|
||||
m.ElectionTicks = electionTicks
|
||||
m.InitialElectionTickAdvance = true
|
||||
m.TickMs = uint(tickDuration / time.Millisecond)
|
||||
m.QuotaBackendBytes = mcfg.quotaBackendBytes
|
||||
m.MaxRequestBytes = mcfg.maxRequestBytes
|
||||
|
@ -695,10 +697,16 @@ func (m *member) Launch() error {
|
|||
if m.PeerTLSInfo == nil {
|
||||
hs.Start()
|
||||
} else {
|
||||
hs.TLS, err = m.PeerTLSInfo.ServerConfig()
|
||||
info := m.PeerTLSInfo
|
||||
hs.TLS, err = info.ServerConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tlsCert, err := tlsutil.NewCert(info.CertFile, info.KeyFile, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hs.TLS.Certificates = []tls.Certificate{*tlsCert}
|
||||
hs.StartTLS()
|
||||
}
|
||||
m.hss = append(m.hss, hs)
|
||||
|
@ -711,10 +719,45 @@ func (m *member) Launch() error {
|
|||
if m.ClientTLSInfo == nil {
|
||||
hs.Start()
|
||||
} else {
|
||||
hs.TLS, err = m.ClientTLSInfo.ServerConfig()
|
||||
info := m.ClientTLSInfo
|
||||
hs.TLS, err = info.ServerConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// baseConfig is called on initial TLS handshake start.
|
||||
//
|
||||
// Previously,
|
||||
// 1. Server has non-empty (*tls.Config).Certificates on client hello
|
||||
// 2. Server calls (*tls.Config).GetCertificate iff:
|
||||
// - Server's (*tls.Config).Certificates is not empty, or
|
||||
// - Client supplies SNI; non-empty (*tls.ClientHelloInfo).ServerName
|
||||
//
|
||||
// When (*tls.Config).Certificates is always populated on initial handshake,
|
||||
// client is expected to provide a valid matching SNI to pass the TLS
|
||||
// verification, thus trigger server (*tls.Config).GetCertificate to reload
|
||||
// TLS assets. However, a cert whose SAN field does not include domain names
|
||||
// but only IP addresses, has empty (*tls.ClientHelloInfo).ServerName, thus
|
||||
// it was never able to trigger TLS reload on initial handshake; first
|
||||
// ceritifcate object was being used, never being updated.
|
||||
//
|
||||
// Now, (*tls.Config).Certificates is created empty on initial TLS client
|
||||
// handshake, in order to trigger (*tls.Config).GetCertificate and populate
|
||||
// rest of the certificates on every new TLS connection, even when client
|
||||
// SNI is empty (e.g. cert only includes IPs).
|
||||
//
|
||||
// This introduces another problem with "httptest.Server":
|
||||
// when server initial certificates are empty, certificates
|
||||
// are overwritten by Go's internal test certs, which have
|
||||
// different SAN fields (e.g. example.com). To work around,
|
||||
// re-overwrite (*tls.Config).Certificates before starting
|
||||
// test server.
|
||||
tlsCert, err := tlsutil.NewCert(info.CertFile, info.KeyFile, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hs.TLS.Certificates = []tls.Certificate{*tlsCert}
|
||||
|
||||
hs.StartTLS()
|
||||
}
|
||||
m.hss = append(m.hss, hs)
|
||||
|
|
|
@ -35,15 +35,19 @@ const (
|
|||
forever = monotime.Time(math.MaxInt64)
|
||||
)
|
||||
|
||||
// MaxLeaseTTL is the maximum lease TTL value
|
||||
const MaxLeaseTTL = 9000000000
|
||||
|
||||
var (
|
||||
leaseBucketName = []byte("lease")
|
||||
|
||||
// maximum number of leases to revoke per second; configurable for tests
|
||||
leaseRevokeRate = 1000
|
||||
|
||||
ErrNotPrimary = errors.New("not a primary lessor")
|
||||
ErrLeaseNotFound = errors.New("lease not found")
|
||||
ErrLeaseExists = errors.New("lease already exists")
|
||||
ErrNotPrimary = errors.New("not a primary lessor")
|
||||
ErrLeaseNotFound = errors.New("lease not found")
|
||||
ErrLeaseExists = errors.New("lease already exists")
|
||||
ErrLeaseTTLTooLarge = errors.New("too large lease TTL")
|
||||
)
|
||||
|
||||
// TxnDelete is a TxnWrite that only permits deletes. Defined here
|
||||
|
@ -199,6 +203,10 @@ func (le *lessor) Grant(id LeaseID, ttl int64) (*Lease, error) {
|
|||
return nil, ErrLeaseNotFound
|
||||
}
|
||||
|
||||
if ttl > MaxLeaseTTL {
|
||||
return nil, ErrLeaseTTLTooLarge
|
||||
}
|
||||
|
||||
// TODO: when lessor is under high load, it should give out lease
|
||||
// with longer TTL to reduce renew load.
|
||||
l := &Lease{
|
||||
|
|
|
@ -54,6 +54,10 @@ type Backend interface {
|
|||
Hash(ignores map[IgnoreKey]struct{}) (uint32, error)
|
||||
// Size returns the current size of the backend.
|
||||
Size() int64
|
||||
// SizeInUse returns the current size of the backend logically in use.
|
||||
// Since the backend can manage free space in a non-byte unit such as
|
||||
// number of pages, the returned value can be not exactly accurate in bytes.
|
||||
SizeInUse() int64
|
||||
Defrag() error
|
||||
ForceCommit()
|
||||
Close() error
|
||||
|
@ -74,6 +78,10 @@ type backend struct {
|
|||
|
||||
// size is the number of bytes in the backend
|
||||
size int64
|
||||
|
||||
// sizeInUse is the number of bytes actually used in the backend
|
||||
sizeInUse int64
|
||||
|
||||
// commits counts number of commits since start
|
||||
commits int64
|
||||
|
||||
|
@ -244,6 +252,10 @@ func (b *backend) Size() int64 {
|
|||
return atomic.LoadInt64(&b.size)
|
||||
}
|
||||
|
||||
func (b *backend) SizeInUse() int64 {
|
||||
return atomic.LoadInt64(&b.sizeInUse)
|
||||
}
|
||||
|
||||
func (b *backend) run() {
|
||||
defer close(b.donec)
|
||||
t := time.NewTimer(b.batchInterval)
|
||||
|
@ -272,18 +284,12 @@ func (b *backend) Commits() int64 {
|
|||
}
|
||||
|
||||
func (b *backend) Defrag() error {
|
||||
err := b.defrag()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// commit to update metadata like db.size
|
||||
b.batchTx.Commit()
|
||||
|
||||
return nil
|
||||
return b.defrag()
|
||||
}
|
||||
|
||||
func (b *backend) defrag() error {
|
||||
now := time.Now()
|
||||
|
||||
// TODO: make this non-blocking?
|
||||
// lock batchTx to ensure nobody is using previous tx, and then
|
||||
// close previous ongoing tx.
|
||||
|
@ -341,7 +347,14 @@ func (b *backend) defrag() error {
|
|||
|
||||
b.readTx.buf.reset()
|
||||
b.readTx.tx = b.unsafeBegin(false)
|
||||
atomic.StoreInt64(&b.size, b.readTx.tx.Size())
|
||||
|
||||
size := b.readTx.tx.Size()
|
||||
db := b.db
|
||||
atomic.StoreInt64(&b.size, size)
|
||||
atomic.StoreInt64(&b.sizeInUse, size-(int64(db.Stats().FreePageN)*int64(db.Info().PageSize)))
|
||||
|
||||
took := time.Since(now)
|
||||
defragDurations.Observe(took.Seconds())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -370,10 +383,10 @@ func defragdb(odb, tmpdb *bolt.DB, limit int) error {
|
|||
}
|
||||
|
||||
tmpb, berr := tmptx.CreateBucketIfNotExists(next)
|
||||
tmpb.FillPercent = 0.9 // for seq write in for each
|
||||
if berr != nil {
|
||||
return berr
|
||||
}
|
||||
tmpb.FillPercent = 0.9 // for seq write in for each
|
||||
|
||||
b.ForEach(func(k, v []byte) error {
|
||||
count++
|
||||
|
@ -402,7 +415,12 @@ func (b *backend) begin(write bool) *bolt.Tx {
|
|||
b.mu.RLock()
|
||||
tx := b.unsafeBegin(write)
|
||||
b.mu.RUnlock()
|
||||
atomic.StoreInt64(&b.size, tx.Size())
|
||||
|
||||
size := tx.Size()
|
||||
db := tx.DB()
|
||||
atomic.StoreInt64(&b.size, size)
|
||||
atomic.StoreInt64(&b.sizeInUse, size-(int64(db.Stats().FreePageN)*int64(db.Info().PageSize)))
|
||||
|
||||
return tx
|
||||
}
|
||||
|
||||
|
|
|
@ -141,15 +141,15 @@ func unsafeForEach(tx *bolt.Tx, bucket []byte, visitor func(k, v []byte) error)
|
|||
// Commit commits a previous tx and begins a new writable one.
|
||||
func (t *batchTx) Commit() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.commit(false)
|
||||
t.Unlock()
|
||||
}
|
||||
|
||||
// CommitAndStop commits the previous tx and does not create a new one.
|
||||
func (t *batchTx) CommitAndStop() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.commit(true)
|
||||
t.Unlock()
|
||||
}
|
||||
|
||||
func (t *batchTx) Unlock() {
|
||||
|
@ -163,21 +163,15 @@ func (t *batchTx) commit(stop bool) {
|
|||
// commit the last tx
|
||||
if t.tx != nil {
|
||||
if t.pending == 0 && !stop {
|
||||
t.backend.mu.RLock()
|
||||
defer t.backend.mu.RUnlock()
|
||||
|
||||
// t.tx.DB()==nil if 'CommitAndStop' calls 'batchTx.commit(true)',
|
||||
// which initializes *bolt.Tx.db and *bolt.Tx.meta as nil; panics t.tx.Size().
|
||||
// Server must make sure 'batchTx.commit(false)' does not follow
|
||||
// 'batchTx.commit(true)' (e.g. stopping backend, and inflight Hash call).
|
||||
atomic.StoreInt64(&t.backend.size, t.tx.Size())
|
||||
return
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
|
||||
// gofail: var beforeCommit struct{}
|
||||
err := t.tx.Commit()
|
||||
// gofail: var afterCommit struct{}
|
||||
|
||||
commitDurations.Observe(time.Since(start).Seconds())
|
||||
atomic.AddInt64(&t.backend.commits, 1)
|
||||
|
||||
|
@ -222,21 +216,21 @@ func (t *batchTxBuffered) Unlock() {
|
|||
|
||||
func (t *batchTxBuffered) Commit() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.commit(false)
|
||||
t.Unlock()
|
||||
}
|
||||
|
||||
func (t *batchTxBuffered) CommitAndStop() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.commit(true)
|
||||
t.Unlock()
|
||||
}
|
||||
|
||||
func (t *batchTxBuffered) commit(stop bool) {
|
||||
// all read txs must be closed to acquire boltdb commit rwlock
|
||||
t.backend.readTx.mu.Lock()
|
||||
defer t.backend.readTx.mu.Unlock()
|
||||
t.unsafeCommit(stop)
|
||||
t.backend.readTx.mu.Unlock()
|
||||
}
|
||||
|
||||
func (t *batchTxBuffered) unsafeCommit(stop bool) {
|
||||
|
|
|
@ -22,7 +22,22 @@ var (
|
|||
Subsystem: "disk",
|
||||
Name: "backend_commit_duration_seconds",
|
||||
Help: "The latency distributions of commit called by backend.",
|
||||
Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
|
||||
|
||||
// lowest bucket start of upper bound 0.001 sec (1 ms) with factor 2
|
||||
// highest bucket start of 0.001 sec * 2^13 == 8.192 sec
|
||||
Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
|
||||
})
|
||||
|
||||
defragDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "disk",
|
||||
Name: "backend_defrag_duration_seconds",
|
||||
Help: "The latency distribution of backend defragmentation.",
|
||||
|
||||
// 100 MB usually takes 1 sec, so start with 10 MB of 100 ms
|
||||
// lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
|
||||
// highest bucket start of 0.1 sec * 2^12 == 409.6 sec
|
||||
Buckets: prometheus.ExponentialBuckets(.1, 2, 13),
|
||||
})
|
||||
|
||||
snapshotDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||
|
@ -30,12 +45,15 @@ var (
|
|||
Subsystem: "disk",
|
||||
Name: "backend_snapshot_duration_seconds",
|
||||
Help: "The latency distribution of backend snapshots.",
|
||||
// 10 ms -> 655 seconds
|
||||
|
||||
// lowest bucket start of upper bound 0.01 sec (10 ms) with factor 2
|
||||
// highest bucket start of 0.01 sec * 2^16 == 655.36 sec
|
||||
Buckets: prometheus.ExponentialBuckets(.01, 2, 17),
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(commitDurations)
|
||||
prometheus.MustRegister(defragDurations)
|
||||
prometheus.MustRegister(snapshotDurations)
|
||||
}
|
||||
|
|
|
@ -150,8 +150,12 @@ func (s *store) compactBarrier(ctx context.Context, ch chan struct{}) {
|
|||
}
|
||||
|
||||
func (s *store) Hash() (hash uint32, revision int64, err error) {
|
||||
start := time.Now()
|
||||
|
||||
s.b.ForceCommit()
|
||||
h, err := s.b.Hash(DefaultIgnores)
|
||||
|
||||
hashDurations.Observe(time.Since(start).Seconds())
|
||||
return h, s.currentRev, err
|
||||
}
|
||||
|
||||
|
@ -245,10 +249,14 @@ func (s *store) Restore(b backend.Backend) error {
|
|||
}
|
||||
|
||||
func (s *store) restore() error {
|
||||
reportDbTotalSizeInBytesMu.Lock()
|
||||
b := s.b
|
||||
|
||||
reportDbTotalSizeInBytesMu.Lock()
|
||||
reportDbTotalSizeInBytes = func() float64 { return float64(b.Size()) }
|
||||
reportDbTotalSizeInBytesMu.Unlock()
|
||||
reportDbTotalSizeInUseInBytesMu.Lock()
|
||||
reportDbTotalSizeInUseInBytes = func() float64 { return float64(b.SizeInUse()) }
|
||||
reportDbTotalSizeInUseInBytesMu.Unlock()
|
||||
|
||||
min, max := newRevBytes(), newRevBytes()
|
||||
revToBytes(revision{main: 1}, min)
|
||||
|
|
|
@ -131,11 +131,23 @@ var (
|
|||
Buckets: prometheus.ExponentialBuckets(100, 2, 14),
|
||||
})
|
||||
|
||||
dbTotalSize = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
dbTotalSizeDebugging = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
Namespace: "etcd_debugging",
|
||||
Subsystem: "mvcc",
|
||||
Name: "db_total_size_in_bytes",
|
||||
Help: "Total size of the underlying database in bytes.",
|
||||
Help: "Total size of the underlying database physically allocated in bytes. Use etcd_mvcc_db_total_size_in_bytes",
|
||||
},
|
||||
func() float64 {
|
||||
reportDbTotalSizeInBytesMu.RLock()
|
||||
defer reportDbTotalSizeInBytesMu.RUnlock()
|
||||
return reportDbTotalSizeInBytes()
|
||||
},
|
||||
)
|
||||
dbTotalSize = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "mvcc",
|
||||
Name: "db_total_size_in_bytes",
|
||||
Help: "Total size of the underlying database physically allocated in bytes.",
|
||||
},
|
||||
func() float64 {
|
||||
reportDbTotalSizeInBytesMu.RLock()
|
||||
|
@ -145,7 +157,35 @@ var (
|
|||
)
|
||||
// overridden by mvcc initialization
|
||||
reportDbTotalSizeInBytesMu sync.RWMutex
|
||||
reportDbTotalSizeInBytes func() float64 = func() float64 { return 0 }
|
||||
reportDbTotalSizeInBytes = func() float64 { return 0 }
|
||||
|
||||
dbTotalSizeInUse = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "mvcc",
|
||||
Name: "db_total_size_in_use_in_bytes",
|
||||
Help: "Total size of the underlying database logically in use in bytes.",
|
||||
},
|
||||
func() float64 {
|
||||
reportDbTotalSizeInUseInBytesMu.RLock()
|
||||
defer reportDbTotalSizeInUseInBytesMu.RUnlock()
|
||||
return reportDbTotalSizeInUseInBytes()
|
||||
},
|
||||
)
|
||||
// overridden by mvcc initialization
|
||||
reportDbTotalSizeInUseInBytesMu sync.RWMutex
|
||||
reportDbTotalSizeInUseInBytes func() float64 = func() float64 { return 0 }
|
||||
|
||||
hashDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "mvcc",
|
||||
Name: "hash_duration_seconds",
|
||||
Help: "The latency distribution of storage hash operation.",
|
||||
|
||||
// 100 MB usually takes 100 ms, so start with 10 MB of 10 ms
|
||||
// lowest bucket start of upper bound 0.01 sec (10 ms) with factor 2
|
||||
// highest bucket start of 0.01 sec * 2^14 == 163.84 sec
|
||||
Buckets: prometheus.ExponentialBuckets(.01, 2, 15),
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -162,7 +202,10 @@ func init() {
|
|||
prometheus.MustRegister(indexCompactionPauseDurations)
|
||||
prometheus.MustRegister(dbCompactionPauseDurations)
|
||||
prometheus.MustRegister(dbCompactionTotalDurations)
|
||||
prometheus.MustRegister(dbTotalSizeDebugging)
|
||||
prometheus.MustRegister(dbTotalSize)
|
||||
prometheus.MustRegister(dbTotalSizeInUse)
|
||||
prometheus.MustRegister(hashDurations)
|
||||
}
|
||||
|
||||
// ReportEventReceived reports that an event is received.
|
||||
|
|
|
@ -188,7 +188,8 @@ func (s *watchableStore) Restore(b backend.Backend) error {
|
|||
}
|
||||
|
||||
for wa := range s.synced.watchers {
|
||||
s.unsynced.watchers.add(wa)
|
||||
wa.restore = true
|
||||
s.unsynced.add(wa)
|
||||
}
|
||||
s.synced = newWatcherGroup()
|
||||
return nil
|
||||
|
@ -479,6 +480,14 @@ type watcher struct {
|
|||
// compacted is set when the watcher is removed because of compaction
|
||||
compacted bool
|
||||
|
||||
// restore is true when the watcher is being restored from leader snapshot
|
||||
// which means that this watcher has just been moved from "synced" to "unsynced"
|
||||
// watcher group, possibly with a future revision when it was first added
|
||||
// to the synced watcher
|
||||
// "unsynced" watcher revision must always be <= current revision,
|
||||
// except when the watcher were to be moved from "synced" watcher group
|
||||
restore bool
|
||||
|
||||
// minRev is the minimum revision update the watcher will accept
|
||||
minRev int64
|
||||
id WatchID
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package mvcc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/coreos/etcd/mvcc/mvccpb"
|
||||
|
@ -238,7 +239,15 @@ func (wg *watcherGroup) chooseAll(curRev, compactRev int64) int64 {
|
|||
minRev := int64(math.MaxInt64)
|
||||
for w := range wg.watchers {
|
||||
if w.minRev > curRev {
|
||||
panic("watcher current revision should not exceed current revision")
|
||||
// after network partition, possibly choosing future revision watcher from restore operation
|
||||
// with watch key "proxy-namespace__lostleader" and revision "math.MaxInt64 - 2"
|
||||
// do not panic when such watcher had been moved from "synced" watcher during restore operation
|
||||
if !w.restore {
|
||||
panic(fmt.Errorf("watcher minimum revision %d should not exceed current revision %d", w.minRev, curRev))
|
||||
}
|
||||
|
||||
// mark 'restore' done, since it's chosen
|
||||
w.restore = false
|
||||
}
|
||||
if w.minRev < compactRev {
|
||||
select {
|
||||
|
|
|
@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cipher_suites.go",
|
||||
"doc.go",
|
||||
"tlsutil.go",
|
||||
],
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tlsutil
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// cipher suites implemented by Go
|
||||
// https://github.com/golang/go/blob/dev.boringcrypto.go1.10/src/crypto/tls/cipher_suites.go
|
||||
var cipherSuites = map[string]uint16{
|
||||
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
}
|
||||
|
||||
// GetCipherSuite returns the corresponding cipher suite,
|
||||
// and boolean value if it is supported.
|
||||
func GetCipherSuite(s string) (uint16, bool) {
|
||||
v, ok := cipherSuites[s]
|
||||
return v, ok
|
||||
}
|
|
@ -69,6 +69,11 @@ type TLSInfo struct {
|
|||
// connection will be closed immediately afterwards.
|
||||
HandshakeFailure func(*tls.Conn, error)
|
||||
|
||||
// CipherSuites is a list of supported cipher suites.
|
||||
// If empty, Go auto-populates it by default.
|
||||
// Note that cipher suites are prioritized in the given order.
|
||||
CipherSuites []uint16
|
||||
|
||||
selfCert bool
|
||||
|
||||
// parseFunc exists to simplify testing. Typically, parseFunc
|
||||
|
@ -162,16 +167,20 @@ func (info TLSInfo) baseConfig() (*tls.Config, error) {
|
|||
return nil, fmt.Errorf("KeyFile and CertFile must both be present[key: %v, cert: %v]", info.KeyFile, info.CertFile)
|
||||
}
|
||||
|
||||
tlsCert, err := tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc)
|
||||
_, err := tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := &tls.Config{
|
||||
Certificates: []tls.Certificate{*tlsCert},
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ServerName: info.ServerName,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ServerName: info.ServerName,
|
||||
}
|
||||
|
||||
if len(info.CipherSuites) > 0 {
|
||||
cfg.CipherSuites = info.CipherSuites
|
||||
}
|
||||
|
||||
// this only reloads certs when there's a client request
|
||||
// TODO: support server-side refresh (e.g. inotify, SIGHUP), caching
|
||||
cfg.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
|
|
|
@ -225,6 +225,7 @@ func (p *peer) send(m raftpb.Message) {
|
|||
plog.MergeWarningf("dropped internal raft message to %s since %s's sending buffer is full (bad/overloaded network)", p.id, name)
|
||||
}
|
||||
plog.Debugf("dropped %s to %s since %s's sending buffer is full", m.Type, p.id, name)
|
||||
sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ func (g *remote) send(m raftpb.Message) {
|
|||
plog.MergeWarningf("dropped internal raft message to %s since sending buffer is full (bad/overloaded network)", g.id)
|
||||
}
|
||||
plog.Debugf("dropped %s to %s since sending buffer is full", m.Type, g.id)
|
||||
sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@ type Transporter interface {
|
|||
// If the connection is active since peer was added, it returns the adding time.
|
||||
// If the connection is currently inactive, it returns zero time.
|
||||
ActiveSince(id types.ID) time.Time
|
||||
// ActivePeers returns the number of active peers.
|
||||
ActivePeers() int
|
||||
// Stop closes the connections and stops the transporter.
|
||||
Stop()
|
||||
}
|
||||
|
@ -362,6 +364,20 @@ func (t *Transport) Resume() {
|
|||
}
|
||||
}
|
||||
|
||||
// ActivePeers returns a channel that closes when an initial
|
||||
// peer connection has been established. Use this to wait until the
|
||||
// first peer connection becomes active.
|
||||
func (t *Transport) ActivePeers() (cnt int) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
for _, p := range t.peers {
|
||||
if !p.activeSince().IsZero() {
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
type nopTransporter struct{}
|
||||
|
||||
func NewNopTransporter() Transporter {
|
||||
|
@ -378,6 +394,7 @@ func (s *nopTransporter) RemovePeer(id types.ID) {}
|
|||
func (s *nopTransporter) RemoveAllPeers() {}
|
||||
func (s *nopTransporter) UpdatePeer(id types.ID, us []string) {}
|
||||
func (s *nopTransporter) ActiveSince(id types.ID) time.Time { return time.Time{} }
|
||||
func (s *nopTransporter) ActivePeers() int { return 0 }
|
||||
func (s *nopTransporter) Stop() {}
|
||||
func (s *nopTransporter) Pause() {}
|
||||
func (s *nopTransporter) Resume() {}
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
var (
|
||||
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
|
||||
MinClusterVersion = "3.0.0"
|
||||
Version = "3.2.13"
|
||||
Version = "3.2.24"
|
||||
APIVersion = "unknown"
|
||||
|
||||
// Git SHA Value will be set during build
|
||||
|
|
|
@ -1 +1 @@
|
|||
../../staging/src/k8s.io/cli-runtime/
|
||||
../../staging/src/k8s.io/cli-runtime
|
|
@ -1 +1 @@
|
|||
../../staging/src/k8s.io/kube-proxy/
|
||||
../../staging/src/k8s.io/kube-proxy
|
|
@ -1 +1 @@
|
|||
../../staging/src/k8s.io/kube-scheduler/
|
||||
../../staging/src/k8s.io/kube-scheduler
|
Loading…
Reference in New Issue