2016-10-25 20:18:51 +03:00
// Copyright 2016 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 main
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
2018-11-16 09:35:41 +03:00
"time"
2016-10-25 20:18:51 +03:00
"github.com/spf13/cobra"
)
var (
rootCommand = & cobra . Command {
Use : "etcd-dump-db" ,
Short : "etcd-dump-db inspects etcd db files." ,
}
listBucketCommand = & cobra . Command {
Use : "list-bucket [data dir or db file path]" ,
Short : "bucket lists all buckets." ,
Run : listBucketCommandFunc ,
}
iterateBucketCommand = & cobra . Command {
2017-12-19 01:13:14 +03:00
Use : "iterate-bucket [data dir or db file path] [bucket name]" ,
2016-10-25 20:18:51 +03:00
Short : "iterate-bucket lists key-value pairs in reverse order." ,
Run : iterateBucketCommandFunc ,
}
getHashCommand = & cobra . Command {
Use : "hash [data dir or db file path]" ,
Short : "hash computes the hash of db file." ,
Run : getHashCommandFunc ,
}
)
2018-11-16 09:35:41 +03:00
var flockTimeout time . Duration
2017-12-19 01:13:14 +03:00
var iterateBucketLimit uint64
var iterateBucketDecode bool
2016-10-25 20:18:51 +03:00
func init ( ) {
2018-11-16 09:35:41 +03:00
rootCommand . PersistentFlags ( ) . DurationVar ( & flockTimeout , "timeout" , 10 * time . Second , "time to wait to obtain a file lock on db file, 0 to block indefinitely" )
2016-10-25 20:18:51 +03:00
iterateBucketCommand . PersistentFlags ( ) . Uint64Var ( & iterateBucketLimit , "limit" , 0 , "max number of key-value pairs to iterate (0< to iterate all)" )
2017-12-19 01:13:14 +03:00
iterateBucketCommand . PersistentFlags ( ) . BoolVar ( & iterateBucketDecode , "decode" , false , "true to decode Protocol Buffer encoded data" )
2016-10-25 20:18:51 +03:00
rootCommand . AddCommand ( listBucketCommand )
rootCommand . AddCommand ( iterateBucketCommand )
rootCommand . AddCommand ( getHashCommand )
}
func main ( ) {
if err := rootCommand . Execute ( ) ; err != nil {
fmt . Fprintln ( os . Stdout , err )
os . Exit ( 1 )
}
}
func listBucketCommandFunc ( cmd * cobra . Command , args [ ] string ) {
if len ( args ) < 1 {
log . Fatalf ( "Must provide at least 1 argument (got %v)" , args )
}
dp := args [ 0 ]
if ! strings . HasSuffix ( dp , "db" ) {
dp = filepath . Join ( snapDir ( dp ) , "db" )
}
if ! existFileOrDir ( dp ) {
log . Fatalf ( "%q does not exist" , dp )
}
bts , err := getBuckets ( dp )
if err != nil {
log . Fatal ( err )
}
for _ , b := range bts {
fmt . Println ( b )
}
}
func iterateBucketCommandFunc ( cmd * cobra . Command , args [ ] string ) {
2017-12-19 01:13:14 +03:00
if len ( args ) != 2 {
log . Fatalf ( "Must provide 2 arguments (got %v)" , args )
2016-10-25 20:18:51 +03:00
}
dp := args [ 0 ]
if ! strings . HasSuffix ( dp , "db" ) {
dp = filepath . Join ( snapDir ( dp ) , "db" )
}
if ! existFileOrDir ( dp ) {
log . Fatalf ( "%q does not exist" , dp )
}
2017-12-19 01:13:14 +03:00
bucket := args [ 1 ]
err := iterateBucket ( dp , bucket , iterateBucketLimit , iterateBucketDecode )
2016-10-25 20:18:51 +03:00
if err != nil {
log . Fatal ( err )
}
}
func getHashCommandFunc ( cmd * cobra . Command , args [ ] string ) {
if len ( args ) < 1 {
log . Fatalf ( "Must provide at least 1 argument (got %v)" , args )
}
dp := args [ 0 ]
if ! strings . HasSuffix ( dp , "db" ) {
dp = filepath . Join ( snapDir ( dp ) , "db" )
}
if ! existFileOrDir ( dp ) {
log . Fatalf ( "%q does not exist" , dp )
}
hash , err := getHash ( dp )
if err != nil {
log . Fatal ( err )
}
fmt . Printf ( "db path: %s\nHash: %d\n" , dp , hash )
}