mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-02 07:26:24 -05:00
refine api, run command and merger (#766)
* mergers code optimize * api log work with pipe * remove inbounds/outbounds by tags *fix rmo flag parse * cmds description and message optimize
This commit is contained in:
parent
2523d77919
commit
7a0af318df
@ -8,7 +8,7 @@ func GetExtensions(formatName string) ([]string, error) {
|
||||
if lowerName == "auto" {
|
||||
return GetAllExtensions(), nil
|
||||
}
|
||||
f, found := mergeLoaderByName[lowerName]
|
||||
f, found := mergersByName[lowerName]
|
||||
if !found {
|
||||
return nil, newError(formatName+" not found", formatName).AtWarning()
|
||||
}
|
||||
@ -18,7 +18,7 @@ func GetExtensions(formatName string) ([]string, error) {
|
||||
// GetAllExtensions get all extensions supported
|
||||
func GetAllExtensions() []string {
|
||||
extensions := make([]string, 0)
|
||||
for _, f := range mergeLoaderByName {
|
||||
for _, f := range mergersByName {
|
||||
extensions = append(extensions, f.Extensions...)
|
||||
}
|
||||
return extensions
|
||||
|
@ -1,40 +0,0 @@
|
||||
package mergers
|
||||
|
||||
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MergeableFormat is a configurable mergeable format of V2Ray config file.
|
||||
type MergeableFormat struct {
|
||||
Name string
|
||||
Extensions []string
|
||||
Loader MergeLoader
|
||||
}
|
||||
|
||||
// MergeLoader is a utility to merge V2Ray config from external source into a map and returns it.
|
||||
type MergeLoader func(input interface{}, m map[string]interface{}) error
|
||||
|
||||
var (
|
||||
mergeLoaderByName = make(map[string]*MergeableFormat)
|
||||
mergeLoaderByExt = make(map[string]*MergeableFormat)
|
||||
)
|
||||
|
||||
// RegisterMergeLoader add a new MergeLoader.
|
||||
func RegisterMergeLoader(format *MergeableFormat) error {
|
||||
if _, found := mergeLoaderByName[format.Name]; found {
|
||||
return newError(format.Name, " already registered.")
|
||||
}
|
||||
mergeLoaderByName[format.Name] = format
|
||||
|
||||
for _, ext := range format.Extensions {
|
||||
lext := strings.ToLower(ext)
|
||||
if f, found := mergeLoaderByExt[lext]; found {
|
||||
return newError(ext, " already registered to ", f.Name)
|
||||
}
|
||||
mergeLoaderByExt[lext] = format
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -12,15 +12,15 @@ import (
|
||||
|
||||
// MergeAs load input and merge as specified format into m
|
||||
func MergeAs(formatName string, input interface{}, m map[string]interface{}) error {
|
||||
f, found := mergeLoaderByName[formatName]
|
||||
f, found := mergersByName[formatName]
|
||||
if !found {
|
||||
return newError("format loader not found for: ", formatName)
|
||||
return newError("format merger not found for: ", formatName)
|
||||
}
|
||||
return f.Loader(input, m)
|
||||
return f.Merge(input, m)
|
||||
}
|
||||
|
||||
// Merge loads inputs and merges them into m
|
||||
// it detects extension for loader selecting, or try all loaders
|
||||
// it detects extension for merger selecting, or try all mergers
|
||||
// if no extension found
|
||||
func Merge(input interface{}, m map[string]interface{}) error {
|
||||
switch v := input.(type) {
|
||||
@ -49,7 +49,7 @@ func Merge(input interface{}, m map[string]interface{}) error {
|
||||
return err
|
||||
}
|
||||
case io.Reader:
|
||||
// read to []byte incase it tries different loaders
|
||||
// read to []byte incase it tries different mergers
|
||||
bs, err := ioutil.ReadAll(v)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -69,24 +69,24 @@ func mergeSingleFile(input interface{}, m map[string]interface{}) error {
|
||||
ext := getExtension(file)
|
||||
if ext != "" {
|
||||
lext := strings.ToLower(ext)
|
||||
f, found := mergeLoaderByExt[lext]
|
||||
f, found := mergersByExt[lext]
|
||||
if !found {
|
||||
return newError("unmergeable format extension: ", ext)
|
||||
}
|
||||
return f.Loader(file, m)
|
||||
return f.Merge(file, m)
|
||||
}
|
||||
}
|
||||
// no extension, try all loaders
|
||||
for _, f := range mergeLoaderByName {
|
||||
// no extension, try all mergers
|
||||
for _, f := range mergersByName {
|
||||
if f.Name == core.FormatAuto {
|
||||
continue
|
||||
}
|
||||
err := f.Loader(input, m)
|
||||
err := f.Merge(input, m)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return newError("tried all loaders but failed for: ", input).AtWarning()
|
||||
return newError("tried all mergers but failed for: ", input).AtWarning()
|
||||
}
|
||||
|
||||
func getExtension(filename string) string {
|
||||
|
@ -11,15 +11,17 @@ import (
|
||||
|
||||
type jsonConverter func(v []byte) ([]byte, error)
|
||||
|
||||
func makeLoader(name string, extensions []string, converter jsonConverter) *MergeableFormat {
|
||||
return &MergeableFormat{
|
||||
// makeMerger makes a merger who merge the format by converting it to JSON
|
||||
func makeMerger(name string, extensions []string, converter jsonConverter) *Merger {
|
||||
return &Merger{
|
||||
Name: name,
|
||||
Extensions: extensions,
|
||||
Loader: makeConvertToJSONLoader(converter),
|
||||
Merge: makeToJSONMergeFunc(converter),
|
||||
}
|
||||
}
|
||||
|
||||
func makeConvertToJSONLoader(converter func(v []byte) ([]byte, error)) MergeLoader {
|
||||
// makeToJSONMergeFunc makes a merge func who merge the format by converting it to JSON
|
||||
func makeToJSONMergeFunc(converter func(v []byte) ([]byte, error)) MergeFunc {
|
||||
return func(input interface{}, target map[string]interface{}) error {
|
||||
if target == nil {
|
||||
panic("merge target is nil")
|
||||
|
@ -1,32 +1,69 @@
|
||||
package mergers
|
||||
|
||||
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v4"
|
||||
"github.com/v2fly/v2ray-core/v4/common"
|
||||
"github.com/v2fly/v2ray-core/v4/infra/conf/json"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(RegisterMergeLoader(makeLoader(
|
||||
common.Must(RegisterMerger(makeMerger(
|
||||
core.FormatJSON,
|
||||
[]string{".json", ".jsonc"},
|
||||
nil,
|
||||
)))
|
||||
common.Must(RegisterMergeLoader(makeLoader(
|
||||
common.Must(RegisterMerger(makeMerger(
|
||||
core.FormatTOML,
|
||||
[]string{".toml"},
|
||||
json.FromTOML,
|
||||
)))
|
||||
common.Must(RegisterMergeLoader(makeLoader(
|
||||
common.Must(RegisterMerger(makeMerger(
|
||||
core.FormatYAML,
|
||||
[]string{".yml", ".yaml"},
|
||||
json.FromYAML,
|
||||
)))
|
||||
common.Must(RegisterMergeLoader(
|
||||
&MergeableFormat{
|
||||
common.Must(RegisterMerger(
|
||||
&Merger{
|
||||
Name: core.FormatAuto,
|
||||
Extensions: nil,
|
||||
Loader: Merge,
|
||||
Merge: Merge,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// Merger is a configurable format merger for V2Ray config files.
|
||||
type Merger struct {
|
||||
Name string
|
||||
Extensions []string
|
||||
Merge MergeFunc
|
||||
}
|
||||
|
||||
// MergeFunc is a utility to merge V2Ray config from external source into a map and returns it.
|
||||
type MergeFunc func(input interface{}, m map[string]interface{}) error
|
||||
|
||||
var (
|
||||
mergersByName = make(map[string]*Merger)
|
||||
mergersByExt = make(map[string]*Merger)
|
||||
)
|
||||
|
||||
// RegisterMerger add a new Merger.
|
||||
func RegisterMerger(format *Merger) error {
|
||||
if _, found := mergersByName[format.Name]; found {
|
||||
return newError(format.Name, " already registered.")
|
||||
}
|
||||
mergersByName[format.Name] = format
|
||||
|
||||
for _, ext := range format.Extensions {
|
||||
lext := strings.ToLower(ext)
|
||||
if f, found := mergersByExt[lext]; found {
|
||||
return newError(ext, " already registered to ", f.Name)
|
||||
}
|
||||
mergersByExt[lext] = format
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package mergers
|
||||
// GetAllNames get names of all formats
|
||||
func GetAllNames() []string {
|
||||
names := make([]string, 0)
|
||||
for _, f := range mergeLoaderByName {
|
||||
for _, f := range mergersByName {
|
||||
names = append(names, f.Name)
|
||||
}
|
||||
return names
|
||||
|
@ -10,15 +10,18 @@ import (
|
||||
|
||||
var cmdAddInbounds = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api adi [--server=127.0.0.1:8080] <c1.json> [c2.json]...",
|
||||
UsageLine: "{{.Exec}} api adi [--server=127.0.0.1:8080] [c1.json] [dir1]...",
|
||||
Short: "add inbounds",
|
||||
Long: `
|
||||
Add inbounds to V2Ray.
|
||||
|
||||
> Make sure you have "HandlerService" set in "config.api.services"
|
||||
of server config.
|
||||
|
||||
Arguments:
|
||||
|
||||
-format <format>
|
||||
Specify the input format.
|
||||
The input format.
|
||||
Available values: "auto", "json", "toml", "yaml"
|
||||
Default: "auto"
|
||||
|
||||
@ -33,7 +36,8 @@ Arguments:
|
||||
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
|
||||
{{.Exec}} {{.LongName}} dir
|
||||
{{.Exec}} {{.LongName}} c1.json c2.yaml
|
||||
`,
|
||||
Run: executeAddInbounds,
|
||||
}
|
||||
@ -44,7 +48,7 @@ func executeAddInbounds(cmd *base.Command, args []string) {
|
||||
cmd.Flag.Parse(args)
|
||||
c, err := helpers.LoadConfig(cmd.Flag.Args(), apiConfigFormat, apiConfigRecursively)
|
||||
if err != nil {
|
||||
base.Fatalf("%s", err)
|
||||
base.Fatalf("failed to load: %s", err)
|
||||
}
|
||||
if len(c.InboundConfigs) == 0 {
|
||||
base.Fatalf("no valid inbound found")
|
||||
|
@ -10,21 +10,27 @@ import (
|
||||
|
||||
var cmdRemoveInbounds = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api rmi [--server=127.0.0.1:8080] <json_file|tag> [json_file] [tag]...",
|
||||
UsageLine: "{{.Exec}} api rmi [--server=127.0.0.1:8080] [c1.json] [dir1]...",
|
||||
Short: "remove inbounds",
|
||||
Long: `
|
||||
Remove inbounds from V2Ray.
|
||||
|
||||
> Make sure you have "HandlerService" set in "config.api.services"
|
||||
of server config.
|
||||
|
||||
Arguments:
|
||||
|
||||
-format <format>
|
||||
Specify the input format.
|
||||
The input format.
|
||||
Available values: "auto", "json", "toml", "yaml"
|
||||
Default: "auto"
|
||||
|
||||
-r
|
||||
Load folders recursively.
|
||||
|
||||
-tags
|
||||
The input are tags instead of config files
|
||||
|
||||
-s, -server <server:port>
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
@ -33,7 +39,9 @@ Arguments:
|
||||
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
|
||||
{{.Exec}} {{.LongName}} dir
|
||||
{{.Exec}} {{.LongName}} c1.json c2.yaml
|
||||
{{.Exec}} {{.LongName}} -tags tag1 tag2
|
||||
`,
|
||||
Run: executeRemoveInbounds,
|
||||
}
|
||||
@ -41,12 +49,23 @@ Example:
|
||||
func executeRemoveInbounds(cmd *base.Command, args []string) {
|
||||
setSharedFlags(cmd)
|
||||
setSharedConfigFlags(cmd)
|
||||
isTags := cmd.Flag.Bool("tags", false, "")
|
||||
cmd.Flag.Parse(args)
|
||||
|
||||
var tags []string
|
||||
if *isTags {
|
||||
tags = cmd.Flag.Args()
|
||||
} else {
|
||||
c, err := helpers.LoadConfig(cmd.Flag.Args(), apiConfigFormat, apiConfigRecursively)
|
||||
if err != nil {
|
||||
base.Fatalf("%s", err)
|
||||
base.Fatalf("failed to load: %s", err)
|
||||
}
|
||||
if len(c.InboundConfigs) == 0 {
|
||||
tags = make([]string, 0)
|
||||
for _, c := range c.InboundConfigs {
|
||||
tags = append(tags, c.Tag)
|
||||
}
|
||||
}
|
||||
if len(tags) == 0 {
|
||||
base.Fatalf("no inbound to remove")
|
||||
}
|
||||
|
||||
@ -54,10 +73,10 @@ func executeRemoveInbounds(cmd *base.Command, args []string) {
|
||||
defer close()
|
||||
|
||||
client := handlerService.NewHandlerServiceClient(conn)
|
||||
for _, c := range c.InboundConfigs {
|
||||
fmt.Println("removing:", c.Tag)
|
||||
for _, tag := range tags {
|
||||
fmt.Println("removing:", tag)
|
||||
r := &handlerService.RemoveInboundRequest{
|
||||
Tag: c.Tag,
|
||||
Tag: tag,
|
||||
}
|
||||
_, err := client.RemoveInbound(ctx, r)
|
||||
if err != nil {
|
||||
|
@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
logService "github.com/v2fly/v2ray-core/v4/app/log/command"
|
||||
"github.com/v2fly/v2ray-core/v4/main/commands/base"
|
||||
@ -15,6 +16,9 @@ var cmdLog = &base.Command{
|
||||
Long: `
|
||||
Follow and print logs from v2ray.
|
||||
|
||||
> Make sure you have "LoggerService" set in "config.api.services"
|
||||
of server config.
|
||||
|
||||
> It ignores -timeout flag while following logs
|
||||
|
||||
Arguments:
|
||||
@ -33,10 +37,10 @@ Example:
|
||||
{{.Exec}} {{.LongName}}
|
||||
{{.Exec}} {{.LongName}} --restart
|
||||
`,
|
||||
Run: executeRestartLogger,
|
||||
Run: executeLog,
|
||||
}
|
||||
|
||||
func executeRestartLogger(cmd *base.Command, args []string) {
|
||||
func executeLog(cmd *base.Command, args []string) {
|
||||
var restart bool
|
||||
cmd.Flag.BoolVar(&restart, "restart", false, "")
|
||||
setSharedFlags(cmd)
|
||||
@ -69,7 +73,8 @@ func followLogger() {
|
||||
if err != nil {
|
||||
base.Fatalf("failed to follow logger: %s", err)
|
||||
}
|
||||
|
||||
// work with `v2ray api log | grep expr`
|
||||
log.SetOutput(os.Stdout)
|
||||
for {
|
||||
resp, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
@ -78,6 +83,6 @@ func followLogger() {
|
||||
if err != nil {
|
||||
base.Fatalf("failed to fetch log: %s", err)
|
||||
}
|
||||
log.Print(resp.Message)
|
||||
log.Println(resp.Message)
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,18 @@ import (
|
||||
|
||||
var cmdAddOutbounds = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api ado [--server=127.0.0.1:8080] <c1.json> [c2.json]...",
|
||||
UsageLine: "{{.Exec}} api ado [--server=127.0.0.1:8080] [c1.json] [dir1]...",
|
||||
Short: "add outbounds",
|
||||
Long: `
|
||||
Add outbounds to V2Ray.
|
||||
|
||||
> Make sure you have "HandlerService" set in "config.api.services"
|
||||
of server config.
|
||||
|
||||
Arguments:
|
||||
|
||||
-format <format>
|
||||
Specify the input format.
|
||||
The input format.
|
||||
Available values: "auto", "json", "toml", "yaml"
|
||||
Default: "auto"
|
||||
|
||||
@ -33,7 +36,8 @@ Arguments:
|
||||
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
|
||||
{{.Exec}} {{.LongName}} dir
|
||||
{{.Exec}} {{.LongName}} c1.json c2.yaml
|
||||
`,
|
||||
Run: executeAddOutbounds,
|
||||
}
|
||||
@ -44,7 +48,7 @@ func executeAddOutbounds(cmd *base.Command, args []string) {
|
||||
cmd.Flag.Parse(args)
|
||||
c, err := helpers.LoadConfig(cmd.Flag.Args(), apiConfigFormat, apiConfigRecursively)
|
||||
if err != nil {
|
||||
base.Fatalf("%s", err)
|
||||
base.Fatalf("failed to load: %s", err)
|
||||
}
|
||||
if len(c.OutboundConfigs) == 0 {
|
||||
base.Fatalf("no valid outbound found")
|
||||
|
@ -10,21 +10,27 @@ import (
|
||||
|
||||
var cmdRemoveOutbounds = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api rmo [--server=127.0.0.1:8080] <json_file|tag> [json_file] [tag]...",
|
||||
UsageLine: "{{.Exec}} api rmo [--server=127.0.0.1:8080] [c1.json] [dir1]...",
|
||||
Short: "remove outbounds",
|
||||
Long: `
|
||||
Remove outbounds from V2Ray.
|
||||
|
||||
> Make sure you have "HandlerService" set in "config.api.services"
|
||||
of server config.
|
||||
|
||||
Arguments:
|
||||
|
||||
-format <format>
|
||||
Specify the input format.
|
||||
The input format.
|
||||
Available values: "auto", "json", "toml", "yaml"
|
||||
Default: "auto"
|
||||
|
||||
-r
|
||||
Load folders recursively.
|
||||
|
||||
-tags
|
||||
The input are tags instead of config files
|
||||
|
||||
-s, -server <server:port>
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
@ -33,20 +39,33 @@ Arguments:
|
||||
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
|
||||
{{.Exec}} {{.LongName}} dir
|
||||
{{.Exec}} {{.LongName}} c1.json c2.yaml
|
||||
{{.Exec}} {{.LongName}} -tags tag1 tag2
|
||||
`,
|
||||
Run: executeRemoveOutbounds,
|
||||
}
|
||||
|
||||
func executeRemoveOutbounds(cmd *base.Command, args []string) {
|
||||
setSharedFlags(cmd)
|
||||
cmd.Flag.Parse(args)
|
||||
setSharedConfigFlags(cmd)
|
||||
isTags := cmd.Flag.Bool("tags", false, "")
|
||||
cmd.Flag.Parse(args)
|
||||
|
||||
var tags []string
|
||||
if *isTags {
|
||||
tags = cmd.Flag.Args()
|
||||
} else {
|
||||
c, err := helpers.LoadConfig(cmd.Flag.Args(), apiConfigFormat, apiConfigRecursively)
|
||||
if err != nil {
|
||||
base.Fatalf("%s", err)
|
||||
base.Fatalf("failed to load: %s", err)
|
||||
}
|
||||
if len(c.OutboundConfigs) == 0 {
|
||||
tags = make([]string, 0)
|
||||
for _, c := range c.OutboundConfigs {
|
||||
tags = append(tags, c.Tag)
|
||||
}
|
||||
}
|
||||
if len(tags) == 0 {
|
||||
base.Fatalf("no outbound to remove")
|
||||
}
|
||||
|
||||
@ -54,10 +73,10 @@ func executeRemoveOutbounds(cmd *base.Command, args []string) {
|
||||
defer close()
|
||||
|
||||
client := handlerService.NewHandlerServiceClient(conn)
|
||||
for _, c := range c.OutboundConfigs {
|
||||
fmt.Println("removing:", c.Tag)
|
||||
for _, tag := range tags {
|
||||
fmt.Println("removing:", tag)
|
||||
r := &handlerService.RemoveOutboundRequest{
|
||||
Tag: c.Tag,
|
||||
Tag: tag,
|
||||
}
|
||||
_, err := client.RemoveOutbound(ctx, r)
|
||||
if err != nil {
|
||||
|
@ -19,13 +19,16 @@ var cmdStats = &base.Command{
|
||||
Long: `
|
||||
Query statistics from V2Ray.
|
||||
|
||||
> Make sure you have "StatsService" set in "config.api.services"
|
||||
of server config.
|
||||
|
||||
Arguments:
|
||||
|
||||
-regexp
|
||||
The patterns are using regexp.
|
||||
|
||||
-reset
|
||||
Fetch values then reset statistics counters to 0.
|
||||
Reset counters to 0 after fetching their values.
|
||||
|
||||
-runtime
|
||||
Get runtime statistics.
|
||||
|
@ -23,17 +23,17 @@ var cmdConvert = &base.Command{
|
||||
Short: "convert config files",
|
||||
Long: `
|
||||
Convert config files between different formats. Files are merged
|
||||
before convert if multiple assigned.
|
||||
before convert.
|
||||
|
||||
Arguments:
|
||||
|
||||
-i, -input <format>
|
||||
Specify the input format.
|
||||
The input format.
|
||||
Available values: "auto", "json", "toml", "yaml"
|
||||
Default: "auto"
|
||||
|
||||
-o, -output <format>
|
||||
Specify the output format
|
||||
The output format
|
||||
Available values: "json", "toml", "yaml", "protobuf" / "pb"
|
||||
Default: "json"
|
||||
|
||||
@ -42,15 +42,15 @@ Arguments:
|
||||
|
||||
Examples:
|
||||
|
||||
{{.Exec}} {{.LongName}} -output=protobuf config.json (1)
|
||||
{{.Exec}} {{.LongName}} -input=toml config.toml (2)
|
||||
{{.Exec}} {{.LongName}} "path/to/dir" (3)
|
||||
{{.Exec}} {{.LongName}} -i yaml -o protobuf c1.yaml <url>.yaml (4)
|
||||
{{.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)
|
||||
|
||||
(1) Convert json to protobuf
|
||||
(2) Convert toml to json
|
||||
(3) Merge json files in dir
|
||||
(4) Merge yaml files and convert to protobuf
|
||||
(1) Merge all supported files in dir and convert to protobuf
|
||||
(2) Convert toml to yaml
|
||||
(3) Merge json files
|
||||
(4) Merge yaml files
|
||||
|
||||
Use "{{.Exec}} help config-merge" for more information about merge.
|
||||
`,
|
||||
@ -81,11 +81,11 @@ func executeConvert(cmd *base.Command, args []string) {
|
||||
|
||||
m, err := helpers.LoadConfigToMap(cmd.Flag.Args(), inputFormat, confDirRecursively)
|
||||
if err != nil {
|
||||
base.Fatalf(err.Error())
|
||||
base.Fatalf("failed to merge: %s", err)
|
||||
}
|
||||
err = merge.ApplyRules(m)
|
||||
if err != nil {
|
||||
base.Fatalf(err.Error())
|
||||
base.Fatalf("failed to apply merge rules: %s", err)
|
||||
}
|
||||
|
||||
var out []byte
|
||||
@ -93,17 +93,17 @@ func executeConvert(cmd *base.Command, args []string) {
|
||||
case core.FormatJSON:
|
||||
out, err = json.Marshal(m)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to marshal json: %s", err)
|
||||
base.Fatalf("failed to convert to json: %s", err)
|
||||
}
|
||||
case core.FormatTOML:
|
||||
out, err = toml.Marshal(m)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to marshal json: %s", err)
|
||||
base.Fatalf("failed to convert to toml: %s", err)
|
||||
}
|
||||
case core.FormatYAML:
|
||||
out, err = yaml.Marshal(m)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to marshal json: %s", err)
|
||||
base.Fatalf("failed to convert to yaml: %s", err)
|
||||
}
|
||||
case core.FormatProtobuf, core.FormatProtobufShort:
|
||||
data, err := json.Marshal(m)
|
||||
@ -121,7 +121,7 @@ func executeConvert(cmd *base.Command, args []string) {
|
||||
}
|
||||
out, err = proto.Marshal(pbConfig)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to marshal proto config: %s", err)
|
||||
base.Fatalf("failed to convert to protobuf: %s", err)
|
||||
}
|
||||
default:
|
||||
base.Errorf("invalid output format: %s", outputFormat)
|
||||
|
@ -8,12 +8,12 @@ var docFormat = &base.Command{
|
||||
UsageLine: "{{.Exec}} format-loader",
|
||||
Short: "config formats and loading",
|
||||
Long: `
|
||||
{{.Exec}} supports different config formats:
|
||||
{{.Exec}} is equipped with multiple loaders to support different
|
||||
config formats:
|
||||
|
||||
* auto
|
||||
The default loader, supports all extensions below.
|
||||
It loads config by format detecting, with mixed
|
||||
formats support.
|
||||
The default loader, supports all formats listed below, with
|
||||
format detecting, and mixed fomats support.
|
||||
|
||||
* json (.json, .jsonc)
|
||||
The json loader, multiple files support, mergeable.
|
||||
@ -21,14 +21,14 @@ var docFormat = &base.Command{
|
||||
* toml (.toml)
|
||||
The toml loader, multiple files support, mergeable.
|
||||
|
||||
* yaml (.yml)
|
||||
* yaml (.yml, .yaml)
|
||||
The yaml loader, multiple files support, mergeable.
|
||||
|
||||
* protobuf / pb (.pb)
|
||||
Single file support, unmergeable.
|
||||
|
||||
|
||||
The following explains how format loaders behave with examples.
|
||||
The following explains how format loaders behaves.
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -25,19 +25,27 @@ var CmdRun = &base.Command{
|
||||
Long: `
|
||||
Run V2Ray with config.
|
||||
|
||||
{{.Exec}} will also use the config directory specified by environment
|
||||
variable "v2ray.location.confdir". If no config found, it tries
|
||||
to load config from one of below:
|
||||
|
||||
1. The default "config.json" in the current directory
|
||||
2. The config file from ENV "v2ray.location.config"
|
||||
3. The stdin if all failed above
|
||||
|
||||
Arguments:
|
||||
|
||||
-c, -config <file>
|
||||
Config file for V2Ray. Multiple assign is accepted.
|
||||
|
||||
-d, -confdir <dir>
|
||||
A dir with config files. Multiple assign is accepted.
|
||||
A directory with config files. Multiple assign is accepted.
|
||||
|
||||
-r
|
||||
Load confdir recursively.
|
||||
|
||||
-format <format>
|
||||
Format of input files. (default "json")
|
||||
Format of config input. (default "auto")
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -16,19 +16,27 @@ var CmdTest = &base.Command{
|
||||
Long: `
|
||||
Test config files, without launching V2Ray server.
|
||||
|
||||
{{.Exec}} will also use the config directory specified by environment
|
||||
variable "v2ray.location.confdir". If no config found, it tries
|
||||
to load config from one of below:
|
||||
|
||||
1. The default "config.json" in the current directory
|
||||
2. The config file from ENV "v2ray.location.config"
|
||||
3. The stdin if all failed above
|
||||
|
||||
Arguments:
|
||||
|
||||
-c, -config <file>
|
||||
Config file for V2Ray. Multiple assign is accepted.
|
||||
|
||||
-d, -confdir <dir>
|
||||
A dir with config files. Multiple assign is accepted.
|
||||
A directory with config files. Multiple assign is accepted.
|
||||
|
||||
-r
|
||||
Load confdir recursively.
|
||||
|
||||
-format <format>
|
||||
Format of input files. (default "json")
|
||||
Format of config input. (default "auto")
|
||||
|
||||
Examples:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user