2021-05-02 16:40:11 -04:00
|
|
|
package jsonv4
|
2020-11-23 10:38:43 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2020-12-02 17:11:24 -05:00
|
|
|
"encoding/json"
|
2020-11-23 10:38:43 -05:00
|
|
|
"os"
|
2020-12-02 17:11:24 -05:00
|
|
|
"strings"
|
2020-11-23 10:38:43 -05:00
|
|
|
|
2021-06-04 19:42:53 -04:00
|
|
|
"github.com/pelletier/go-toml"
|
2021-02-21 10:02:42 -05:00
|
|
|
"google.golang.org/protobuf/proto"
|
2021-06-04 19:42:53 -04:00
|
|
|
"gopkg.in/yaml.v2"
|
2021-02-21 10:02:42 -05:00
|
|
|
|
|
|
|
core "github.com/v2fly/v2ray-core/v4"
|
2021-10-28 06:34:19 -04:00
|
|
|
"github.com/v2fly/v2ray-core/v4/infra/conf/jsonpb"
|
2021-02-21 10:02:42 -05:00
|
|
|
"github.com/v2fly/v2ray-core/v4/infra/conf/merge"
|
2021-10-28 06:34:19 -04:00
|
|
|
"github.com/v2fly/v2ray-core/v4/infra/conf/v2jsonpb"
|
2020-12-04 09:32:55 -05:00
|
|
|
"github.com/v2fly/v2ray-core/v4/main/commands/base"
|
2021-02-21 10:02:42 -05:00
|
|
|
"github.com/v2fly/v2ray-core/v4/main/commands/helpers"
|
2020-11-23 10:38:43 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
var cmdConvert = &base.Command{
|
2020-12-02 17:11:24 -05:00
|
|
|
CustomFlags: true,
|
|
|
|
UsageLine: "{{.Exec}} convert [c1.json] [<url>.json] [dir1] ...",
|
2021-02-21 10:02:42 -05:00
|
|
|
Short: "convert config files",
|
2020-11-23 10:38:43 -05:00
|
|
|
Long: `
|
2020-12-02 17:11:24 -05:00
|
|
|
Convert config files between different formats. Files are merged
|
2021-03-10 16:03:26 -05:00
|
|
|
before convert.
|
2020-11-28 09:06:03 -05:00
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
2021-02-21 10:02:42 -05:00
|
|
|
-i, -input <format>
|
2021-03-10 16:03:26 -05:00
|
|
|
The input format.
|
2021-02-21 10:02:42 -05:00
|
|
|
Available values: "auto", "json", "toml", "yaml"
|
|
|
|
Default: "auto"
|
2020-12-02 17:11:24 -05:00
|
|
|
|
2021-02-21 10:02:42 -05:00
|
|
|
-o, -output <format>
|
2021-03-10 16:03:26 -05:00
|
|
|
The output format
|
2021-01-01 09:18:47 -05:00
|
|
|
Available values: "json", "toml", "yaml", "protobuf" / "pb"
|
2020-12-02 17:11:24 -05:00
|
|
|
Default: "json"
|
|
|
|
|
2020-11-28 09:06:03 -05:00
|
|
|
-r
|
2021-02-21 10:02:42 -05:00
|
|
|
Load folders recursively.
|
2020-11-23 10:38:43 -05:00
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
2021-03-10 16:03:26 -05:00
|
|
|
{{.Exec}} {{.LongName}} -output=protobuf "path/to/dir" (1)
|
|
|
|
{{.Exec}} {{.LongName}} -o=yaml config.toml (2)
|
|
|
|
{{.Exec}} {{.LongName}} c1.json c2.json (3)
|
|
|
|
{{.Exec}} {{.LongName}} -output=yaml c1.yaml <url>.yaml (4)
|
2020-12-02 17:11:24 -05:00
|
|
|
|
2021-03-10 16:03:26 -05:00
|
|
|
(1) Merge all supported files in dir and convert to protobuf
|
|
|
|
(2) Convert toml to yaml
|
|
|
|
(3) Merge json files
|
|
|
|
(4) Merge yaml files
|
2020-12-02 17:11:24 -05:00
|
|
|
|
|
|
|
Use "{{.Exec}} help config-merge" for more information about merge.
|
2020-11-23 10:38:43 -05:00
|
|
|
`,
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
cmdConvert.Run = executeConvert // break init loop
|
|
|
|
}
|
|
|
|
|
2020-12-02 17:11:24 -05:00
|
|
|
var (
|
|
|
|
inputFormat string
|
|
|
|
outputFormat string
|
|
|
|
confDirRecursively bool
|
|
|
|
)
|
2020-11-28 09:06:03 -05:00
|
|
|
|
2020-12-02 17:11:24 -05:00
|
|
|
func setConfArgs(cmd *base.Command) {
|
2021-02-21 10:02:42 -05:00
|
|
|
cmd.Flag.StringVar(&inputFormat, "input", core.FormatAuto, "")
|
|
|
|
cmd.Flag.StringVar(&inputFormat, "i", core.FormatAuto, "")
|
2020-12-02 17:11:24 -05:00
|
|
|
cmd.Flag.StringVar(&outputFormat, "output", "json", "")
|
|
|
|
cmd.Flag.StringVar(&outputFormat, "o", "json", "")
|
2020-12-20 00:35:52 -05:00
|
|
|
cmd.Flag.BoolVar(&confDirRecursively, "r", false, "")
|
2020-12-02 17:11:24 -05:00
|
|
|
}
|
2021-11-27 01:32:07 -05:00
|
|
|
|
2020-11-23 10:38:43 -05:00
|
|
|
func executeConvert(cmd *base.Command, args []string) {
|
2020-12-02 17:11:24 -05:00
|
|
|
setConfArgs(cmd)
|
|
|
|
cmd.Flag.Parse(args)
|
|
|
|
inputFormat = strings.ToLower(inputFormat)
|
|
|
|
outputFormat = strings.ToLower(outputFormat)
|
|
|
|
|
2021-09-05 06:27:56 -04:00
|
|
|
inputFormatMerge := inputFormat
|
|
|
|
if inputFormat == "jsonv5" {
|
|
|
|
inputFormatMerge = "json"
|
|
|
|
}
|
|
|
|
m, err := helpers.LoadConfigToMap(cmd.Flag.Args(), inputFormatMerge, confDirRecursively)
|
2021-02-21 10:02:42 -05:00
|
|
|
if err != nil {
|
2021-03-10 16:03:26 -05:00
|
|
|
base.Fatalf("failed to merge: %s", err)
|
2021-02-21 10:02:42 -05:00
|
|
|
}
|
|
|
|
err = merge.ApplyRules(m)
|
|
|
|
if err != nil {
|
2021-03-10 16:03:26 -05:00
|
|
|
base.Fatalf("failed to apply merge rules: %s", err)
|
2020-11-23 10:38:43 -05:00
|
|
|
}
|
|
|
|
|
2021-02-21 10:02:42 -05:00
|
|
|
var out []byte
|
2020-12-02 17:11:24 -05:00
|
|
|
switch outputFormat {
|
2021-02-21 10:02:42 -05:00
|
|
|
case core.FormatJSON:
|
2020-12-02 17:11:24 -05:00
|
|
|
out, err = json.Marshal(m)
|
|
|
|
if err != nil {
|
2021-03-10 16:03:26 -05:00
|
|
|
base.Fatalf("failed to convert to json: %s", err)
|
2020-12-02 17:11:24 -05:00
|
|
|
}
|
2021-02-21 10:02:42 -05:00
|
|
|
case core.FormatTOML:
|
2021-01-01 09:18:47 -05:00
|
|
|
out, err = toml.Marshal(m)
|
|
|
|
if err != nil {
|
2021-03-10 16:03:26 -05:00
|
|
|
base.Fatalf("failed to convert to toml: %s", err)
|
2021-01-01 09:18:47 -05:00
|
|
|
}
|
2021-02-21 10:02:42 -05:00
|
|
|
case core.FormatYAML:
|
2020-12-02 17:11:24 -05:00
|
|
|
out, err = yaml.Marshal(m)
|
|
|
|
if err != nil {
|
2021-03-10 16:03:26 -05:00
|
|
|
base.Fatalf("failed to convert to yaml: %s", err)
|
2020-12-02 17:11:24 -05:00
|
|
|
}
|
2021-02-21 10:02:42 -05:00
|
|
|
case core.FormatProtobuf, core.FormatProtobufShort:
|
2020-12-02 17:11:24 -05:00
|
|
|
data, err := json.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
base.Fatalf("failed to marshal json: %s", err)
|
|
|
|
}
|
|
|
|
r := bytes.NewReader(data)
|
2021-09-05 06:27:56 -04:00
|
|
|
pbConfig, err := core.LoadConfig(inputFormat, r)
|
2020-12-02 17:11:24 -05:00
|
|
|
if err != nil {
|
|
|
|
base.Fatalf(err.Error())
|
|
|
|
}
|
|
|
|
out, err = proto.Marshal(pbConfig)
|
|
|
|
if err != nil {
|
2021-03-10 16:03:26 -05:00
|
|
|
base.Fatalf("failed to convert to protobuf: %s", err)
|
2020-12-02 17:11:24 -05:00
|
|
|
}
|
2021-06-19 10:09:13 -04:00
|
|
|
case jsonpb.FormatProtobufJSONPB:
|
|
|
|
data, err := json.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
base.Fatalf("failed to marshal json: %s", err)
|
|
|
|
}
|
|
|
|
r := bytes.NewReader(data)
|
2021-09-05 06:27:56 -04:00
|
|
|
pbConfig, err := core.LoadConfig(inputFormat, r)
|
2021-06-19 10:09:13 -04:00
|
|
|
if err != nil {
|
|
|
|
base.Fatalf(err.Error())
|
|
|
|
}
|
|
|
|
w := bytes.NewBuffer(nil)
|
2021-11-27 04:16:41 -05:00
|
|
|
err = jsonpb.DumpJSONPb(pbConfig, w)
|
2021-06-19 10:09:13 -04:00
|
|
|
if err != nil {
|
|
|
|
base.Fatalf(err.Error())
|
|
|
|
}
|
|
|
|
out = w.Bytes()
|
2021-06-19 15:20:31 -04:00
|
|
|
case v2jsonpb.FormatProtobufV2JSONPB:
|
|
|
|
data, err := json.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
base.Fatalf("failed to marshal json: %s", err)
|
|
|
|
}
|
|
|
|
r := bytes.NewReader(data)
|
2021-09-05 06:27:56 -04:00
|
|
|
pbConfig, err := core.LoadConfig(inputFormat, r)
|
2021-06-19 15:20:31 -04:00
|
|
|
if err != nil {
|
|
|
|
base.Fatalf(err.Error())
|
|
|
|
}
|
|
|
|
out, err = v2jsonpb.DumpV2JsonPb(pbConfig)
|
|
|
|
if err != nil {
|
|
|
|
base.Fatalf(err.Error())
|
|
|
|
}
|
2020-12-02 17:11:24 -05:00
|
|
|
default:
|
|
|
|
base.Errorf("invalid output format: %s", outputFormat)
|
|
|
|
base.Errorf("Run '%s help %s' for details.", base.CommandEnv.Exec, cmd.LongName())
|
|
|
|
base.Exit()
|
2020-11-23 10:38:43 -05:00
|
|
|
}
|
|
|
|
|
2020-12-02 17:11:24 -05:00
|
|
|
if _, err := os.Stdout.Write(out); err != nil {
|
2021-02-21 10:02:42 -05:00
|
|
|
base.Fatalf("failed to write stdout: %s", err)
|
2020-11-23 10:38:43 -05:00
|
|
|
}
|
|
|
|
}
|