mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
conf: support render configure file using environment variables
This commit is contained in:
parent
b61cb14c8f
commit
25cfda5768
@ -17,13 +17,10 @@ package client
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
ini "github.com/vaughan0/go-ini"
|
|
||||||
|
|
||||||
"github.com/fatedier/frp/client/proxy"
|
"github.com/fatedier/frp/client/proxy"
|
||||||
"github.com/fatedier/frp/g"
|
"github.com/fatedier/frp/g"
|
||||||
"github.com/fatedier/frp/models/config"
|
"github.com/fatedier/frp/models/config"
|
||||||
@ -53,14 +50,13 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
log.Info("Http request: [/api/reload]")
|
log.Info("Http request: [/api/reload]")
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(g.GlbClientCfg.CfgFile)
|
content, err := config.GetRenderedConfFromFile(g.GlbClientCfg.CfgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res.Code = 1
|
res.Code = 1
|
||||||
res.Msg = err.Error()
|
res.Msg = err.Error()
|
||||||
log.Error("reload frpc config file error: %v", err)
|
log.Error("reload frpc config file error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
content := string(b)
|
|
||||||
|
|
||||||
newCommonCfg, err := config.UnmarshalClientConfFromIni(nil, content)
|
newCommonCfg, err := config.UnmarshalClientConfFromIni(nil, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -70,15 +66,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conf, err := ini.LoadFile(g.GlbClientCfg.CfgFile)
|
pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(g.GlbClientCfg.User, content, newCommonCfg.Start)
|
||||||
if err != nil {
|
|
||||||
res.Code = 1
|
|
||||||
res.Msg = err.Error()
|
|
||||||
log.Error("reload frpc config file error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(g.GlbClientCfg.User, conf, newCommonCfg.Start)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res.Code = 3
|
res.Code = 3
|
||||||
res.Msg = err.Error()
|
res.Msg = err.Error()
|
||||||
|
@ -17,7 +17,6 @@ package sub
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -27,7 +26,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
ini "github.com/vaughan0/go-ini"
|
|
||||||
|
|
||||||
"github.com/fatedier/frp/client"
|
"github.com/fatedier/frp/client"
|
||||||
"github.com/fatedier/frp/g"
|
"github.com/fatedier/frp/g"
|
||||||
@ -111,9 +109,9 @@ func handleSignal(svr *client.Service) {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseClientCommonCfg(fileType int, filePath string) (err error) {
|
func parseClientCommonCfg(fileType int, content string) (err error) {
|
||||||
if fileType == CfgFileTypeIni {
|
if fileType == CfgFileTypeIni {
|
||||||
err = parseClientCommonCfgFromIni(filePath)
|
err = parseClientCommonCfgFromIni(content)
|
||||||
} else if fileType == CfgFileTypeCmd {
|
} else if fileType == CfgFileTypeCmd {
|
||||||
err = parseClientCommonCfgFromCmd()
|
err = parseClientCommonCfgFromCmd()
|
||||||
}
|
}
|
||||||
@ -121,8 +119,6 @@ func parseClientCommonCfg(fileType int, filePath string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
g.GlbClientCfg.CfgFile = cfgFile
|
|
||||||
|
|
||||||
err = g.GlbClientCfg.ClientCommonConf.Check()
|
err = g.GlbClientCfg.ClientCommonConf.Check()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -130,13 +126,7 @@ func parseClientCommonCfg(fileType int, filePath string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseClientCommonCfgFromIni(filePath string) (err error) {
|
func parseClientCommonCfgFromIni(content string) (err error) {
|
||||||
b, err := ioutil.ReadFile(filePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
content := string(b)
|
|
||||||
|
|
||||||
cfg, err := config.UnmarshalClientConfFromIni(&g.GlbClientCfg.ClientCommonConf, content)
|
cfg, err := config.UnmarshalClientConfFromIni(&g.GlbClientCfg.ClientCommonConf, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -175,17 +165,19 @@ func parseClientCommonCfgFromCmd() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runClient(cfgFilePath string) (err error) {
|
func runClient(cfgFilePath string) (err error) {
|
||||||
err = parseClientCommonCfg(CfgFileTypeIni, cfgFilePath)
|
var content string
|
||||||
|
content, err = config.GetRenderedConfFromFile(cfgFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.GlbClientCfg.CfgFile = cfgFilePath
|
||||||
|
|
||||||
|
err = parseClientCommonCfg(CfgFileTypeIni, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conf, err := ini.LoadFile(cfgFilePath)
|
pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(g.GlbClientCfg.User, content, g.GlbClientCfg.Start)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(g.GlbClientCfg.User, conf, g.GlbClientCfg.Start)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -100,7 +99,13 @@ var rootCmd = &cobra.Command{
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
if cfgFile != "" {
|
if cfgFile != "" {
|
||||||
err = parseServerCommonCfg(CfgFileTypeIni, cfgFile)
|
var content string
|
||||||
|
content, err = config.GetRenderedConfFromFile(cfgFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g.GlbServerCfg.CfgFile = cfgFile
|
||||||
|
err = parseServerCommonCfg(CfgFileTypeIni, content)
|
||||||
} else {
|
} else {
|
||||||
err = parseServerCommonCfg(CfgFileTypeCmd, "")
|
err = parseServerCommonCfg(CfgFileTypeCmd, "")
|
||||||
}
|
}
|
||||||
@ -123,9 +128,9 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseServerCommonCfg(fileType int, filePath string) (err error) {
|
func parseServerCommonCfg(fileType int, content string) (err error) {
|
||||||
if fileType == CfgFileTypeIni {
|
if fileType == CfgFileTypeIni {
|
||||||
err = parseServerCommonCfgFromIni(filePath)
|
err = parseServerCommonCfgFromIni(content)
|
||||||
} else if fileType == CfgFileTypeCmd {
|
} else if fileType == CfgFileTypeCmd {
|
||||||
err = parseServerCommonCfgFromCmd()
|
err = parseServerCommonCfgFromCmd()
|
||||||
}
|
}
|
||||||
@ -133,8 +138,6 @@ func parseServerCommonCfg(fileType int, filePath string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
g.GlbServerCfg.CfgFile = filePath
|
|
||||||
|
|
||||||
err = g.GlbServerCfg.ServerCommonConf.Check()
|
err = g.GlbServerCfg.ServerCommonConf.Check()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -144,13 +147,7 @@ func parseServerCommonCfg(fileType int, filePath string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseServerCommonCfgFromIni(filePath string) (err error) {
|
func parseServerCommonCfgFromIni(content string) (err error) {
|
||||||
b, err := ioutil.ReadFile(filePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
content := string(b)
|
|
||||||
|
|
||||||
cfg, err := config.UnmarshalServerConfFromIni(&g.GlbServerCfg.ServerCommonConf, content)
|
cfg, err := config.UnmarshalServerConfFromIni(&g.GlbServerCfg.ServerCommonConf, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -885,9 +885,15 @@ func ParseRangeSection(name string, section ini.Section) (sections map[string]in
|
|||||||
|
|
||||||
// if len(startProxy) is 0, start all
|
// if len(startProxy) is 0, start all
|
||||||
// otherwise just start proxies in startProxy map
|
// otherwise just start proxies in startProxy map
|
||||||
func LoadAllConfFromIni(prefix string, conf ini.File, startProxy map[string]struct{}) (
|
func LoadAllConfFromIni(prefix string, content string, startProxy map[string]struct{}) (
|
||||||
proxyConfs map[string]ProxyConf, visitorConfs map[string]VisitorConf, err error) {
|
proxyConfs map[string]ProxyConf, visitorConfs map[string]VisitorConf, err error) {
|
||||||
|
|
||||||
|
conf, errRet := ini.Load(strings.NewReader(content))
|
||||||
|
if errRet != nil {
|
||||||
|
err = errRet
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if prefix != "" {
|
if prefix != "" {
|
||||||
prefix += "."
|
prefix += "."
|
||||||
}
|
}
|
||||||
|
64
models/config/value.go
Normal file
64
models/config/value.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
glbEnvs map[string]string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
glbEnvs = make(map[string]string)
|
||||||
|
envs := os.Environ()
|
||||||
|
for _, env := range envs {
|
||||||
|
kv := strings.Split(env, "=")
|
||||||
|
if len(kv) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
glbEnvs[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Values struct {
|
||||||
|
Envs map[string]string // environment vars
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetValues() *Values {
|
||||||
|
return &Values{
|
||||||
|
Envs: glbEnvs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RenderContent(in string) (out string, err error) {
|
||||||
|
tmpl, errRet := template.New("frp").Parse(in)
|
||||||
|
if errRet != nil {
|
||||||
|
err = errRet
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := bytes.NewBufferString("")
|
||||||
|
v := GetValues()
|
||||||
|
err = tmpl.Execute(buffer, v)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
out = buffer.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRenderedConfFromFile(path string) (out string, err error) {
|
||||||
|
var b []byte
|
||||||
|
b, err = ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
content := string(b)
|
||||||
|
|
||||||
|
out, err = RenderContent(content)
|
||||||
|
return
|
||||||
|
}
|
72
tests/ci/template_test.go
Normal file
72
tests/ci/template_test.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package ci
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/tests/config"
|
||||||
|
"github.com/fatedier/frp/tests/consts"
|
||||||
|
"github.com/fatedier/frp/tests/util"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
const FRPS_TEMPLATE_CONF = `
|
||||||
|
[common]
|
||||||
|
bind_addr = 0.0.0.0
|
||||||
|
bind_port = {{ .Envs.SERVER_PORT }}
|
||||||
|
log_file = console
|
||||||
|
# debug, info, warn, error
|
||||||
|
log_level = debug
|
||||||
|
token = 123456
|
||||||
|
`
|
||||||
|
|
||||||
|
const FRPC_TEMPLATE_CONF = `
|
||||||
|
[common]
|
||||||
|
server_addr = 127.0.0.1
|
||||||
|
server_port = 20000
|
||||||
|
log_file = console
|
||||||
|
# debug, info, warn, error
|
||||||
|
log_level = debug
|
||||||
|
token = {{ .Envs.FRP_TOKEN }}
|
||||||
|
|
||||||
|
[tcp]
|
||||||
|
type = tcp
|
||||||
|
local_port = 10701
|
||||||
|
remote_port = {{ .Envs.TCP_REMOTE_PORT }}
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestConfTemplate(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
frpsCfgPath, err := config.GenerateConfigFile(consts.FRPS_NORMAL_CONFIG, FRPS_TEMPLATE_CONF)
|
||||||
|
if assert.NoError(err) {
|
||||||
|
defer os.Remove(frpsCfgPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
frpcCfgPath, err := config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_TEMPLATE_CONF)
|
||||||
|
if assert.NoError(err) {
|
||||||
|
defer os.Remove(frpcCfgPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
frpsProcess := util.NewProcess("env", []string{"SERVER_PORT=20000", consts.FRPS_BIN_PATH, "-c", frpsCfgPath})
|
||||||
|
err = frpsProcess.Start()
|
||||||
|
if assert.NoError(err) {
|
||||||
|
defer frpsProcess.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
frpcProcess := util.NewProcess("env", []string{"FRP_TOKEN=123456", "TCP_REMOTE_PORT=20801", consts.FRPC_BIN_PATH, "-c", frpcCfgPath})
|
||||||
|
err = frpcProcess.Start()
|
||||||
|
if assert.NoError(err) {
|
||||||
|
defer frpcProcess.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(250 * time.Millisecond)
|
||||||
|
|
||||||
|
// test tcp1
|
||||||
|
res, err := util.SendTcpMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(consts.TEST_TCP_ECHO_STR, res)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user