convert.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package all
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "github.com/pelletier/go-toml"
  6. "google.golang.org/protobuf/proto"
  7. "os"
  8. "strings"
  9. "github.com/v2fly/v2ray-core/v4/infra/conf/serial"
  10. "github.com/v2fly/v2ray-core/v4/main/commands/base"
  11. "gopkg.in/yaml.v2"
  12. )
  13. var cmdConvert = &base.Command{
  14. CustomFlags: true,
  15. UsageLine: "{{.Exec}} convert [c1.json] [<url>.json] [dir1] ...",
  16. Short: "Convert config files",
  17. Long: `
  18. Convert config files between different formats. Files are merged
  19. before convert if multiple assigned.
  20. Arguments:
  21. -i, -input
  22. Specify the input format.
  23. Available values: "json", "toml", "yaml"
  24. Default: "json"
  25. -o, -output
  26. Specify the output format
  27. Available values: "json", "toml", "yaml", "protobuf" / "pb"
  28. Default: "json"
  29. -r
  30. Load confdir recursively.
  31. Examples:
  32. {{.Exec}} {{.LongName}} -output=protobuf config.json (1)
  33. {{.Exec}} {{.LongName}} -input=toml config.toml (2)
  34. {{.Exec}} {{.LongName}} "path/to/dir" (3)
  35. {{.Exec}} {{.LongName}} -i yaml -o protobuf c1.yaml <url>.yaml (4)
  36. (1) Convert json to protobuf
  37. (2) Convert toml to json
  38. (3) Merge json files in dir
  39. (4) Merge yaml files and convert to protobuf
  40. Use "{{.Exec}} help config-merge" for more information about merge.
  41. `,
  42. }
  43. func init() {
  44. cmdConvert.Run = executeConvert // break init loop
  45. }
  46. var (
  47. inputFormat string
  48. outputFormat string
  49. confDirRecursively bool
  50. )
  51. var formatExtensions = map[string][]string{
  52. "json": {".json", ".jsonc"},
  53. "toml": {".toml"},
  54. "yaml": {".yaml", ".yml"},
  55. }
  56. func setConfArgs(cmd *base.Command) {
  57. cmd.Flag.StringVar(&inputFormat, "input", "json", "")
  58. cmd.Flag.StringVar(&inputFormat, "i", "json", "")
  59. cmd.Flag.StringVar(&outputFormat, "output", "json", "")
  60. cmd.Flag.StringVar(&outputFormat, "o", "json", "")
  61. cmd.Flag.BoolVar(&confDirRecursively, "r", false, "")
  62. }
  63. func executeConvert(cmd *base.Command, args []string) {
  64. setConfArgs(cmd)
  65. cmd.Flag.Parse(args)
  66. unnamed := cmd.Flag.Args()
  67. inputFormat = strings.ToLower(inputFormat)
  68. outputFormat = strings.ToLower(outputFormat)
  69. files := resolveFolderToFiles(unnamed, formatExtensions[inputFormat], confDirRecursively)
  70. if len(files) == 0 {
  71. base.Fatalf("empty config list")
  72. }
  73. m := mergeConvertToMap(files, inputFormat)
  74. var (
  75. out []byte
  76. err error
  77. )
  78. switch outputFormat {
  79. case "json":
  80. out, err = json.Marshal(m)
  81. if err != nil {
  82. base.Fatalf("failed to marshal json: %s", err)
  83. }
  84. case "toml":
  85. out, err = toml.Marshal(m)
  86. if err != nil {
  87. base.Fatalf("failed to marshal json: %s", err)
  88. }
  89. case "yaml":
  90. out, err = yaml.Marshal(m)
  91. if err != nil {
  92. base.Fatalf("failed to marshal json: %s", err)
  93. }
  94. case "pb", "protobuf":
  95. data, err := json.Marshal(m)
  96. if err != nil {
  97. base.Fatalf("failed to marshal json: %s", err)
  98. }
  99. r := bytes.NewReader(data)
  100. cf, err := serial.DecodeJSONConfig(r)
  101. if err != nil {
  102. base.Fatalf("failed to decode json: %s", err)
  103. }
  104. pbConfig, err := cf.Build()
  105. if err != nil {
  106. base.Fatalf(err.Error())
  107. }
  108. out, err = proto.Marshal(pbConfig)
  109. if err != nil {
  110. base.Fatalf("failed to marshal proto config: %s", err)
  111. }
  112. default:
  113. base.Errorf("invalid output format: %s", outputFormat)
  114. base.Errorf("Run '%s help %s' for details.", base.CommandEnv.Exec, cmd.LongName())
  115. base.Exit()
  116. }
  117. if _, err := os.Stdout.Write(out); err != nil {
  118. base.Fatalf("failed to write proto config: %s", err)
  119. }
  120. }