func main() { // Get connection env variable. conn := common.GetEnv() // Options. version := flag.Bool("version", false, "Version") node := flag.String("node", "", "Etcd node") port := flag.String("port", "2379", "Etcd port") dir := flag.String("dir", "/", "Etcd directory") format := flag.String("format", "JSON", "Data serialization format YAML, TOML or JSON") output := flag.String("output", "", "Output file") flag.Parse() // Print version. if *version { fmt.Printf("etcd-export %s\n", common.Version) os.Exit(0) } // Validate input. if len(conn) < 1 && *node == "" { log.Fatalf("You need to specify Etcd host.") } // Get data format. f, err := iodatafmt.Format(*format) if err != nil { log.Fatal(err.Error()) } // Setup Etcd client. if *node != "" { conn = []string{fmt.Sprintf("http://%v:%v", *node, *port)} } client := etcd.NewClient(conn) // Export data. res, err := client.Get(*dir, true, true) if err != nil { log.Fatal(err.Error()) } m := etcdmap.Map(res.Node) // Write output. if *output != "" { iodatafmt.Write(*output, m, f) } else { iodatafmt.Print(m, f) } }
// exportCommandFunc exports data as either JSON, YAML or TOML. func exportFunc(dir string, sort bool, file string, f iodatafmt.DataFmt, c *cli.Context, ki client.KeysAPI) { ctx, cancel := contextWithCommandTimeout(c) resp, err := ki.Get(ctx, dir, &client.GetOptions{Sort: sort, Recursive: true}) cancel() if err != nil { fatal(err.Error()) } // Export and write output. m := etcdmap.Map(resp.Node) if file != "" { iodatafmt.Write(file, m, f) } else { iodatafmt.Print(m, f) } }
// Get document. func (s *session) Get(p string, table bool, dirName string) (interface{}, int, error) { res, err := s.keysAPI.Get(context.TODO(), p, &client.GetOptions{Recursive: true}) if err != nil { // Document doesn't exist. if cerr, ok := err.(client.Error); ok && cerr.Code == 100 { return nil, http.StatusNotFound, err } // Error retrieving document. return nil, http.StatusInternalServerError, err } if table { arr := etcdmap.Array(res.Node, dirName) return arr, http.StatusOK, nil } return etcdmap.Map(res.Node), http.StatusOK, nil }
// validateCommandFunc validate data using JSON Schema. func validateCommandFunc(c *cli.Context) { if len(c.Args()) == 0 { fatal("You need to specify directory") } dir := c.Args()[0] // Remove trailing slash. if dir != "/" { dir = strings.TrimRight(dir, "/") } infof("Using dir: %s", dir) // Load configuration file. e := loadConfig(c) // New dir API. ki := newKeyAPI(e) // Map directory to routes. var schema string for _, r := range e.Routes { match, err := regexp.MatchString(r.Regexp, dir) if err != nil { fatal(err.Error()) } if match { schema = r.Schema } } if schema == "" && len(c.Args()) == 1 { fatal("You need to specify JSON schema URI") } if len(c.Args()) > 1 { schema = c.Args()[1] } // Get directory. ctx, cancel := contextWithCommandTimeout(c) resp, err := ki.Get(ctx, dir, &client.GetOptions{Recursive: true}) cancel() if err != nil { fatal(err.Error()) } m := etcdmap.Map(resp.Node) // Validate directory. infof("Using JSON schema: %s", schema) schemaLoader := gojsonschema.NewReferenceLoader(schema) docLoader := gojsonschema.NewGoLoader(m) result, err := gojsonschema.Validate(schemaLoader, docLoader) if err != nil { fatal(err.Error()) } // Print results. if !result.Valid() { for _, err := range result.Errors() { fmt.Printf("%s: %s\n", strings.Replace(err.Context().String("/"), "(root)", dir, 1), err.Description()) } } }