mirror of
https://github.com/luscis/openlan.git
synced 2025-10-09 02:20:11 +08:00
fea: config: support ghodss yaml
This commit is contained in:
3
Makefile
3
Makefile
@@ -119,8 +119,9 @@ install: env linux ## install packages
|
||||
@mkdir -p $(LINUX_DIR)/etc/openlan/switch
|
||||
@cp -rf $(SD)/dist/resource/confd.schema.json $(LINUX_DIR)/etc/openlan/switch
|
||||
@cp -rf $(SD)/dist/resource/switch.json.example $(LINUX_DIR)/etc/openlan/switch
|
||||
@mkdir -p $(LINUX_DIR)/etc/openlan/switch/acl
|
||||
@cp -rf $(SD)/dist/resource/acl-1.json.example $(LINUX_DIR)/etc/openlan/switch/acl
|
||||
@mkdir -p $(LINUX_DIR)/etc/openlan/switch/network
|
||||
@cp -rf $(SD)/dist/resource/acl-1.json.example $(LINUX_DIR)/etc/openlan/switch/network
|
||||
@cp -rf $(SD)/dist/resource/default.json.example $(LINUX_DIR)/etc/openlan/switch/network
|
||||
@cp -rf $(SD)/dist/resource/network.json.example $(LINUX_DIR)/etc/openlan/switch/network
|
||||
@cp -rf $(SD)/dist/resource/ipsec.json.example $(LINUX_DIR)/etc/openlan/switch/network
|
||||
|
@@ -2,8 +2,8 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"gopkg.in/yaml.v2"
|
||||
"os"
|
||||
"strconv"
|
||||
"text/template"
|
||||
|
@@ -121,6 +121,9 @@ func (c Cmd) Tmpl() string {
|
||||
}
|
||||
|
||||
func (c Cmd) Out(data interface{}, format string, tmpl string) error {
|
||||
if tmpl == "" && format == "table" {
|
||||
format = "json"
|
||||
}
|
||||
return api.Out(data, format, tmpl)
|
||||
}
|
||||
|
||||
|
@@ -26,13 +26,17 @@ func (u Config) List(c *cli.Context) error {
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
cfg := &config.Switch{}
|
||||
if err := clt.GetJSON(url, cfg); err == nil {
|
||||
name := c.String("network")
|
||||
format := c.String("format")
|
||||
if format == "yaml" {
|
||||
cfg.Format()
|
||||
} else {
|
||||
format = "json"
|
||||
}
|
||||
if len(name) > 0 {
|
||||
obj := cfg.GetNetwork(name)
|
||||
return u.Out(obj, format, "")
|
||||
} else {
|
||||
return u.Out(cfg, format, "")
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -163,6 +167,9 @@ func (u Config) Commands(app *api.App) {
|
||||
Name: "list",
|
||||
Usage: "Display all configuration",
|
||||
Aliases: []string{"ls"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "network", Value: ""},
|
||||
},
|
||||
Action: u.List,
|
||||
},
|
||||
{
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package v5
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/luscis/openlan/cmd/api"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
@@ -16,11 +16,10 @@ func (u Network) Url(prefix, name string) string {
|
||||
|
||||
func (u Network) List(c *cli.Context) error {
|
||||
url := u.Url(c.String("url"), "")
|
||||
url += "?format=" + c.String("format")
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
if data, err := clt.GetBody(url); err == nil {
|
||||
fmt.Println(string(data))
|
||||
return nil
|
||||
var items []schema.Network
|
||||
if err := clt.GetJSON(url, &items); err == nil {
|
||||
return u.Out(items, c.String("format"), "")
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
14
dist/resource/acl-1.json.example
vendored
14
dist/resource/acl-1.json.example
vendored
@@ -2,19 +2,19 @@
|
||||
"name": "acl-1",
|
||||
"rules": [
|
||||
{
|
||||
"dst": "192.168.77.121",
|
||||
"proto": "tcp",
|
||||
"dport": 443,
|
||||
"destination": "192.168.77.121",
|
||||
"protocol": "tcp",
|
||||
"destPort": "443",
|
||||
"action": "drop"
|
||||
},
|
||||
{
|
||||
"dst": "192.168.10.0/24",
|
||||
"destination": "192.168.10.0/24",
|
||||
"action": "drop"
|
||||
},
|
||||
{
|
||||
"src": "192.168.100.0/24",
|
||||
"proto": "udp",
|
||||
"sport": 68,
|
||||
"source": "192.168.100.0/24",
|
||||
"protocol": "udp",
|
||||
"sourcePort": "68",
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
|
6
dist/resource/default.json.example
vendored
6
dist/resource/default.json.example
vendored
@@ -5,8 +5,8 @@
|
||||
"address": "172.32.99.40/24"
|
||||
},
|
||||
"subnet": {
|
||||
"start": "172.32.99.250",
|
||||
"end": "172.32.99.254",
|
||||
"startAt": "172.32.99.250",
|
||||
"endAt": "172.32.99.254",
|
||||
"netmask": "255.255.255.0"
|
||||
},
|
||||
"routes": [
|
||||
@@ -19,5 +19,5 @@
|
||||
"listen": "0.0.0.0:3294",
|
||||
"subnet": "172.32.194.0/24"
|
||||
},
|
||||
"acl": "acl-99"
|
||||
"acl": "acl-1"
|
||||
}
|
||||
|
7
dist/resource/network.json.example
vendored
7
dist/resource/network.json.example
vendored
@@ -5,10 +5,9 @@
|
||||
"address": "172.32.100.40/24"
|
||||
},
|
||||
"subnet": {
|
||||
"start": "172.32.100.250",
|
||||
"end": "172.32.100.254",
|
||||
"netmask": "255.255.255.0",
|
||||
"dns": "8.8.8.8,8.8.4.4",
|
||||
"startAt": "172.32.100.250",
|
||||
"endAt": "172.32.100.254",
|
||||
"netmask": "255.255.255.0"
|
||||
},
|
||||
"hosts": [
|
||||
{
|
||||
|
19
dist/resource/network.yaml.example
vendored
Normal file
19
dist/resource/network.yaml.example
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: hongkong
|
||||
provider: openlan
|
||||
bridge:
|
||||
network: hongkong
|
||||
name: br-hongkong
|
||||
address: 192.168.10.33/24
|
||||
subnet:
|
||||
netmask: 255.255.255.0
|
||||
links:
|
||||
- connection: jw.lightstars.xyz:23
|
||||
username: admin
|
||||
password: wamiibiot7xyjxd4ur3gztkw
|
||||
crypt:
|
||||
algorithm: aes-128
|
||||
secret: 477bb0c55edb
|
||||
routes:
|
||||
- prefix: 103.252.112.0/23
|
||||
nexthop: 192.168.10.11
|
||||
outputs: []
|
41
dist/resource/openssl
vendored
41
dist/resource/openssl
vendored
@@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
action=$1
|
||||
|
||||
if [ "$action" == "" ]; then
|
||||
echo "$0 <cert|ca|sign|show>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -e "ca" ] || mkdir ca
|
||||
[ -e "cert" ] || mkdir cert
|
||||
|
||||
if [ "$action" == "cert" ]; then
|
||||
source cert.vars
|
||||
[ -e "cert/key" ] || openssl genrsa -out cert/key 2048
|
||||
# openssl rsa -in key -noout -text
|
||||
[ -e "cert/key.pub" ] || openssl rsa -in cert/key -pubout -out cert/key.pub
|
||||
# openssl rsa -pubin -in key.pub -noout -text
|
||||
# using private to sign pem and generate a csr request.
|
||||
[ -e "cert/crt.csr" ] || openssl req -new -key cert/key -out cert/crt.csr -subj "/C=$C/ST=$ST/L=$NJ/O=$O/OU=$OU/CN=$CN/emailAddress=$emailAddress"
|
||||
fi
|
||||
|
||||
if [ "$action" == "ca" ]; then #### CA &x509
|
||||
source ca.vars
|
||||
[ -e "ca/ca.key" ] || openssl genrsa -out ca/ca.key 2048
|
||||
[ -e "ca/ca.crt" ] || openssl req -new -x509 -days 3650 -key ca/ca.key -out ca/ca.crt -subj "/C=$C/ST=$ST/L=$L/O=$O/OU=$OU/CN=$CN/emailAddress=$emailAddress"
|
||||
fi
|
||||
|
||||
if [ "$action" == "sign" ]; then
|
||||
#### Sign cert using myself ca
|
||||
[ -e "cert/crt" ] || openssl x509 -req -days 730 -in cert/crt.csr -CA ./ca/ca.crt -CAkey ./ca/ca.key -CAcreateserial -out cert/crt -sha256 -extfile cert.ext
|
||||
fi
|
||||
|
||||
if [ "$action" == "show" ]; then
|
||||
echo "### ca.crt"
|
||||
openssl x509 -in ca/ca.crt -noout -text
|
||||
echo "### crt.csr"
|
||||
openssl req -noout -text -in cert/crt.csr
|
||||
echo "### crt"
|
||||
openssl x509 -in cert/crt -noout -text
|
||||
fi
|
2
dist/resource/point.json.full.example
vendored
2
dist/resource/point.json.full.example
vendored
@@ -12,7 +12,7 @@
|
||||
"insecure": true
|
||||
},
|
||||
"crypt": {
|
||||
"algo": "aes-256",
|
||||
"algorithm": "aes-256",
|
||||
"secret": "1f4ee82b5eb6"
|
||||
}
|
||||
}
|
||||
|
2
dist/resource/proxy.json.example
vendored
2
dist/resource/proxy.json.example
vendored
@@ -26,7 +26,7 @@
|
||||
"password": "cb2ff088a34d"
|
||||
},
|
||||
"cert": {
|
||||
"dir": "/var/openlan/cert"
|
||||
"directory": "/var/openlan/cert"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
2
dist/resource/switch.json.example
vendored
2
dist/resource/switch.json.example
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"cert": {
|
||||
"dir": "/var/openlan/cert"
|
||||
"directory": "/var/openlan/cert"
|
||||
},
|
||||
"http": {
|
||||
"public": "/var/openlan/public"
|
||||
|
8
dist/resource/switch.json.full.example
vendored
8
dist/resource/switch.json.full.example
vendored
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"protocol": "tls",
|
||||
"cert": {
|
||||
"dir": "/var/openlan/cert"
|
||||
"directory": "/var/openlan/cert"
|
||||
},
|
||||
"http": {
|
||||
"public": "/var/openlan/public"
|
||||
},
|
||||
"crypt": {
|
||||
"algo": "aes-128",
|
||||
"algorithm": "aes-128",
|
||||
"secret": "cb2ff088a34d"
|
||||
},
|
||||
"inspect": [
|
||||
@@ -21,9 +21,9 @@
|
||||
"protocol": "tcp",
|
||||
"match": "tcp",
|
||||
"destination": "0.0.0.0/0",
|
||||
"dport": 80,
|
||||
"destPort": 80,
|
||||
"jump": "DNAT",
|
||||
"to-destination": "100.44.85.6:80"
|
||||
"toDestination": "100.44.85.6:80"
|
||||
}
|
||||
],
|
||||
"ldap": {
|
||||
|
5
dist/resource/switch.yaml.example
vendored
Normal file
5
dist/resource/switch.yaml.example
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
protocol: tcp
|
||||
listen: :10002
|
||||
crypt:
|
||||
algorithm: xor
|
||||
secret: cb2ff088a34d
|
4
dist/resource/v1024.json.example
vendored
4
dist/resource/v1024.json.example
vendored
@@ -9,8 +9,8 @@
|
||||
"address": "192.168.55.1/24"
|
||||
},
|
||||
"subnet": {
|
||||
"start": "192.168.55.100",
|
||||
"end": "192.168.55.130"
|
||||
"startAt": "192.168.55.100",
|
||||
"endAt": "192.168.55.130"
|
||||
},
|
||||
"dhcp": "enable",
|
||||
"outputs": [
|
||||
|
1
go.mod
1
go.mod
@@ -21,6 +21,7 @@ require (
|
||||
github.com/coreos/go-systemd/v22 v22.3.2
|
||||
github.com/danieldin95/go-openvswitch v0.0.5
|
||||
github.com/docker/libnetwork v0.5.6 // indirect
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-ldap/ldap v3.0.3+incompatible
|
||||
github.com/go-logr/logr v1.1.0
|
||||
github.com/go-logr/stdr v1.1.0
|
||||
|
2
go.sum
2
go.sum
@@ -54,6 +54,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
||||
github.com/docker/libnetwork v0.5.6 h1:hnGiypBsZR6PW1I8lqaBHh06U6LCJbI3IhOvfsZiymY=
|
||||
github.com/docker/libnetwork v0.5.6/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
|
@@ -7,13 +7,13 @@ type ACL struct {
|
||||
}
|
||||
|
||||
type ACLRule struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
SrcIp string `json:"src,omitempty" yaml:"source,omitempty"`
|
||||
DstIp string `json:"dst,omitempty" yaml:"destination,omitempty"`
|
||||
Proto string `json:"proto,omitempty" yaml:"protocol,omitempty"`
|
||||
SrcPort string `json:"sport,omitempty" yaml:"destPort,omitempty"`
|
||||
DstPort string `json:"dport,omitempty" yaml:"sourcePort,omitempty"`
|
||||
Action string `json:"action,omitempty" yaml:"action,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
SrcIp string `json:"source,omitempty"`
|
||||
DstIp string `json:"destination,omitempty"`
|
||||
Proto string `json:"protocol,omitempty"`
|
||||
SrcPort string `json:"sourcePort,omitempty"`
|
||||
DstPort string `json:"destPort,omitempty"`
|
||||
Action string `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
func (ru *ACLRule) Correct() {
|
||||
|
@@ -2,14 +2,14 @@ package config
|
||||
|
||||
type Bridge struct {
|
||||
Network string `json:"network"`
|
||||
Peer string `json:"peer,omitempty" yaml:"peer,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
IPMtu int `json:"mtu,omitempty" yaml:"mtu,omitempty"`
|
||||
Address string `json:"address,omitempty" yaml:"address,omitempty"`
|
||||
Provider string `json:"provider,omitempty" yaml:"provider,omitempty"`
|
||||
Stp string `json:"stp,omitempty" yaml:"stp,omitempty"`
|
||||
Delay int `json:"delay,omitempty" yaml:"delay,omitempty"`
|
||||
Mss int `json:"tcpMss,omitempty" yaml:"tcpMss,omitempty"`
|
||||
Peer string `json:"peer,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
IPMtu int `json:"mtu,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Stp string `json:"stp,omitempty"`
|
||||
Delay int `json:"delay,omitempty"`
|
||||
Mss int `json:"tcpMss,omitempty"`
|
||||
}
|
||||
|
||||
func (br *Bridge) Correct() {
|
||||
|
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type Crypt struct {
|
||||
Algo string `json:"algo,omitempty" yaml:"algorithm"`
|
||||
Algo string `json:"algorithm,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ func (c *Crypt) Default() {
|
||||
}
|
||||
|
||||
type Cert struct {
|
||||
Dir string `json:"dir" yaml:"directory"`
|
||||
CrtFile string `json:"crt" yaml:"cert"`
|
||||
KeyFile string `json:"key" yaml:"key"`
|
||||
CaFile string `json:"ca" yaml:"rootCa"`
|
||||
Dir string `json:"directory"`
|
||||
CrtFile string `json:"cert"`
|
||||
KeyFile string `json:"key"`
|
||||
CaFile string `json:"rootCa"`
|
||||
Insecure bool `json:"insecure"`
|
||||
}
|
||||
|
||||
|
@@ -20,8 +20,8 @@ func VarDir(name ...string) string {
|
||||
}
|
||||
|
||||
type Log struct {
|
||||
File string `json:"file,omitempty" yaml:"file,omitempty"`
|
||||
Verbose int `json:"level,omitempty" yaml:"level,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
Verbose int `json:"level,omitempty"`
|
||||
}
|
||||
|
||||
func LogFile(file string) string {
|
||||
@@ -33,7 +33,7 @@ func LogFile(file string) string {
|
||||
|
||||
type Http struct {
|
||||
Listen string `json:"listen,omitempty"`
|
||||
Public string `json:"public,omitempty" yaml:"public,omitempty"`
|
||||
Public string `json:"public,omitempty"`
|
||||
}
|
||||
|
||||
func CorrectAddr(listen *string, port int) {
|
||||
|
@@ -8,15 +8,6 @@ var Manager = manager{
|
||||
Switch: &Switch{},
|
||||
}
|
||||
|
||||
func GetNetwork(name string) *Network {
|
||||
for _, network := range Manager.Switch.Network {
|
||||
if network.Name == name {
|
||||
return network
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Reload() {
|
||||
Manager.Switch.Reload()
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package config
|
||||
|
||||
type Dhcp struct {
|
||||
Name string `json:"name,omitempty" yaml:"name"`
|
||||
Bridge *Bridge `json:"bridge,omitempty" yaml:"bridge,omitempty"`
|
||||
Subnet *IpSubnet `json:"subnet,omitempty" yaml:"subnet,omitempty"`
|
||||
Hosts []HostLease `json:"hosts,omitempty" yaml:"hosts,omitempty"`
|
||||
Routes []PrefixRoute `json:"routes,omitempty" yaml:"routes,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Bridge *Bridge `json:"bridge,omitempty"`
|
||||
Subnet *Subnet `json:"subnet,omitempty"`
|
||||
Hosts []HostLease `json:"hosts,omitempty"`
|
||||
Routes []PrefixRoute `json:"routes,omitempty"`
|
||||
}
|
||||
|
@@ -29,14 +29,14 @@ func SetLocalUdp(port string) {
|
||||
}
|
||||
|
||||
type EspState struct {
|
||||
Local string `json:"local,omitempty" yaml:"local,omitempty"`
|
||||
LocalIp net.IP `json:"local_addr" yaml:"localAddr"`
|
||||
Remote string `json:"remote,omitempty" yaml:"remote,omitempty"`
|
||||
RemotePort int `json:"remote_port" yaml:"remotePort"`
|
||||
RemoteIp net.IP `json:"remote_addr" yaml:"remoteAddr"`
|
||||
Encap string `json:"encapsulation" yaml:"encapsulation"`
|
||||
Auth string `json:"auth,omitempty" yaml:"auth,omitempty"`
|
||||
Crypt string `json:"crypt,omitempty" yaml:"crypt,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
LocalIp net.IP `json:"localAddr,omitempty"`
|
||||
Remote string `json:"remote,omitempty"`
|
||||
RemotePort int `json:"remotePort,omitempty"`
|
||||
RemoteIp net.IP `json:"remoteAddr,omitempty"`
|
||||
Encap string `json:"encapsulation,omitempty"`
|
||||
Auth string `json:"auth,omitempty"`
|
||||
Crypt string `json:"crypt,omitempty"`
|
||||
}
|
||||
|
||||
func (s *EspState) Padding(value string, size int) string {
|
||||
@@ -90,8 +90,8 @@ func (s *EspState) Correct(obj *EspState) {
|
||||
|
||||
type ESPPolicy struct {
|
||||
Source string `json:"source,omitempty"`
|
||||
Dest string `json:"destination,omitempty" yaml:"destination"`
|
||||
Priority int `json:"priority"`
|
||||
Dest string `json:"destination,omitempty"`
|
||||
Priority int `json:"priority,omitempty"`
|
||||
}
|
||||
|
||||
func (p *ESPPolicy) Correct() {
|
||||
@@ -102,12 +102,12 @@ func (p *ESPPolicy) Correct() {
|
||||
}
|
||||
|
||||
type ESPMember struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
Peer string `json:"peer"`
|
||||
Spi int `json:"spi"`
|
||||
State EspState `json:"state"`
|
||||
Policies []*ESPPolicy `json:"policies" yaml:"policies"`
|
||||
Policies []*ESPPolicy `json:"policies"`
|
||||
}
|
||||
|
||||
func (m *ESPMember) Correct(state *EspState) {
|
||||
@@ -178,9 +178,9 @@ func (m *ESPMember) RemovePolicy(dest string) bool {
|
||||
type ESPSpecifies struct {
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address,omitempty"`
|
||||
State EspState `json:"state,omitempty" yaml:"state,omitempty"`
|
||||
State EspState `json:"state,omitempty"`
|
||||
Members []*ESPMember `json:"members"`
|
||||
Listen string `json:"listen,omitempty" yaml:"listen,omitempty"`
|
||||
Listen string `json:"listen,omitempty"`
|
||||
}
|
||||
|
||||
func (n *ESPSpecifies) Correct() {
|
||||
|
@@ -3,9 +3,9 @@ package config
|
||||
type FabricSpecifies struct {
|
||||
Mss int `json:"tcpMss,omitempty"`
|
||||
Fragment bool `json:"fragment"`
|
||||
Driver string `json:"driver,omitempty" yaml:"driver,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Tunnels []*FabricTunnel `json:"tunnels" yaml:"tunnels"`
|
||||
Driver string `json:"driver,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Tunnels []*FabricTunnel `json:"tunnels"`
|
||||
}
|
||||
|
||||
func (n *FabricSpecifies) Correct() {
|
||||
@@ -53,10 +53,10 @@ func (n *FabricSpecifies) DelTunnel(remote string) bool {
|
||||
}
|
||||
|
||||
type FabricTunnel struct {
|
||||
DstPort uint32 `json:"dport" yaml:"destPort"`
|
||||
DstPort uint32 `json:"destPort"`
|
||||
Remote string `json:"remote"`
|
||||
Local string `json:"local,omitempty" yaml:"local,omitempty"`
|
||||
Mode string `json:"mode,omitempty" yaml:"mode,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
Mode string `json:"mode,omitempty"`
|
||||
}
|
||||
|
||||
func (c *FabricTunnel) Correct() {
|
||||
|
@@ -1,18 +1,18 @@
|
||||
package config
|
||||
|
||||
type FlowRule struct {
|
||||
Table string `json:"table,omitempty" yaml:"table,omitempty"`
|
||||
Chain string `json:"chain,omitempty" yaml:"chain,omitempty"`
|
||||
Input string `json:"input,omitempty" yaml:"input,omitempty"`
|
||||
Source string `json:"source,omitempty" yaml:"source,omitempty"`
|
||||
ToSource string `json:"to-source,omitempty" yaml:"toSource,omitempty"`
|
||||
Dest string `json:"destination,omitempty" yaml:"destination,omitempty"`
|
||||
ToDest string `json:"to-destination" yaml:"toDestination,omitempty"`
|
||||
Output string `json:"output,omitempty" yaml:"output,omitempty"`
|
||||
Comment string `json:"comment,omitempty" yaml:"comment,omitempty"`
|
||||
Proto string `json:"protocol,omitempty" yaml:"protocol,omitempty"`
|
||||
Match string `json:"match,omitempty" yaml:"match,omitempty"`
|
||||
DstPort string `json:"dport,omitempty" yaml:"destPort,omitempty"`
|
||||
SrcPort string `json:"sport,omitempty" yaml:"sourcePort,omitempty"`
|
||||
Jump string `json:"jump,omitempty" yaml:"jump,omitempty"` // SNAT/RETURN/MASQUERADE
|
||||
Table string `json:"table,omitempty"`
|
||||
Chain string `json:"chain,omitempty"`
|
||||
Input string `json:"input,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
ToSource string `json:"toSource,omitempty"`
|
||||
Dest string `json:"destination,omitempty"`
|
||||
ToDest string `json:"toDestination"`
|
||||
Output string `json:"output,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
Proto string `json:"protocol,omitempty"`
|
||||
Match string `json:"match,omitempty"`
|
||||
DstPort string `json:"destPort,omitempty"`
|
||||
SrcPort string `json:"sourcePort,omitempty"`
|
||||
Jump string `json:"jump,omitempty"` // SNAT/RETURN/MASQUERADE
|
||||
}
|
||||
|
@@ -2,9 +2,9 @@ package config
|
||||
|
||||
type LDAP struct {
|
||||
Server string `json:"server"`
|
||||
BindDN string `json:"bindDN" yaml:"bindDN"`
|
||||
BindPass string `json:"bindPass" yaml:"bindPass"`
|
||||
BaseDN string `json:"baseDN" yaml:"baseDN"`
|
||||
BindDN string `json:"bindDN"`
|
||||
BindPass string `json:"bindPass"`
|
||||
BaseDN string `json:"baseDN"`
|
||||
Attribute string `json:"attribute"`
|
||||
Filter string `json:"filter"`
|
||||
Tls bool `json:"tLS"`
|
||||
|
@@ -3,12 +3,12 @@ package config
|
||||
import "github.com/luscis/openlan/pkg/libol"
|
||||
|
||||
type Queue struct {
|
||||
SockWr int `json:"swr"` // per frames about 1572(1514+4+20+20+14)bytes
|
||||
SockRd int `json:"srd"` // per frames
|
||||
TapWr int `json:"twr"` // per frames about 1572((1514+4+20+20+14))bytes
|
||||
TapRd int `json:"trd"` // per frames
|
||||
VirSnd int `json:"vsd"`
|
||||
VirWrt int `json:"vwr"`
|
||||
SockWr int `json:"sockWr"` // per frames about 1572(1514+4+20+20+14)bytes
|
||||
SockRd int `json:"sockRd"` // per frames
|
||||
TapWr int `json:"tapWr"` // per frames about 1572((1514+4+20+20+14))bytes
|
||||
TapRd int `json:"tapRd"` // per frames
|
||||
VirSnd int `json:"virSnd"`
|
||||
VirWrt int `json:"virWrt"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -7,21 +7,21 @@ import (
|
||||
)
|
||||
|
||||
type Network struct {
|
||||
ConfDir string `json:"-" yaml:"-"`
|
||||
ConfDir string `json:"-"`
|
||||
File string `json:"file"`
|
||||
Alias string `json:"-" yaml:"-"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Provider string `json:"provider,omitempty" yaml:"provider,omitempty"`
|
||||
Bridge *Bridge `json:"bridge,omitempty" yaml:"bridge,omitempty"`
|
||||
Subnet *IpSubnet `json:"subnet,omitempty" yaml:"subnet,omitempty"`
|
||||
OpenVPN *OpenVPN `json:"openvpn,omitempty" yaml:"openvpn,omitempty"`
|
||||
Links []Point `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
Hosts []HostLease `json:"hosts,omitempty" yaml:"hosts,omitempty"`
|
||||
Routes []PrefixRoute `json:"routes,omitempty" yaml:"routes,omitempty"`
|
||||
Acl string `json:"acl,omitempty" yaml:"acl,omitempty"`
|
||||
Specifies interface{} `json:"specifies,omitempty" yaml:"specifies,omitempty"`
|
||||
Dhcp string `json:"dhcp,omitempty" yaml:"dhcp,omitempty"`
|
||||
Outputs []Output `json:"outputs" yaml:"outputs"`
|
||||
Alias string `json:"-"`
|
||||
Name string `json:"name"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Bridge *Bridge `json:"bridge,omitempty"`
|
||||
Subnet *Subnet `json:"subnet,omitempty"`
|
||||
OpenVPN *OpenVPN `json:"openvpn,omitempty"`
|
||||
Links []Point `json:"links,omitempty"`
|
||||
Hosts []HostLease `json:"hosts,omitempty"`
|
||||
Routes []PrefixRoute `json:"routes,omitempty"`
|
||||
Acl string `json:"acl,omitempty"`
|
||||
Specifies interface{} `json:"specifies,omitempty"`
|
||||
Dhcp string `json:"dhcp,omitempty"`
|
||||
Outputs []Output `json:"outputs"`
|
||||
}
|
||||
|
||||
func (n *Network) Correct() {
|
||||
@@ -53,7 +53,7 @@ func (n *Network) Correct() {
|
||||
}
|
||||
default:
|
||||
if n.Subnet == nil {
|
||||
n.Subnet = &IpSubnet{}
|
||||
n.Subnet = &Subnet{}
|
||||
}
|
||||
ipAddr := ""
|
||||
ipMask := ""
|
||||
|
@@ -11,28 +11,28 @@ type OpenVPN struct {
|
||||
Network string `json:"network"`
|
||||
Directory string `json:"directory"`
|
||||
Listen string `json:"listen"`
|
||||
Protocol string `json:"protocol"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
Subnet string `json:"subnet"`
|
||||
Device string `json:"device"`
|
||||
Version int `json:"version"`
|
||||
Auth string `json:"auth"` // xauth or cert.
|
||||
DhPem string `json:"dhPem" yaml:"dhPem"`
|
||||
Version int `json:"version,omitempty"`
|
||||
Auth string `json:"auth,omitempty"` // xauth or cert.
|
||||
DhPem string `json:"dhPem"`
|
||||
RootCa string `json:"rootCa"`
|
||||
ServerCrt string `json:"cert" yaml:"cert"`
|
||||
ServerKey string `json:"key" yaml:"key"`
|
||||
TlsAuth string `json:"tlsAuth" yaml:"tlsAuth"`
|
||||
ServerCrt string `json:"cert"`
|
||||
ServerKey string `json:"key"`
|
||||
TlsAuth string `json:"tlsAuth"`
|
||||
Cipher string `json:"cipher"`
|
||||
Routes []string `json:"-" yaml:"-"`
|
||||
Renego int `json:"renego,omitempty" yaml:"renego,omitempty"`
|
||||
Script string `json:"-" yaml:"-"`
|
||||
Push []string `json:"push,omitempty" yaml:"push,omitempty"`
|
||||
Clients []*OpenVPNClient `json:"clients,omitempty" yaml:"clients,omitempty"`
|
||||
Routes []string `json:"-"`
|
||||
Renego int `json:"renego,omitempty"`
|
||||
Script string `json:"-"`
|
||||
Push []string `json:"push,omitempty"`
|
||||
Clients []*OpenVPNClient `json:"clients,omitempty"`
|
||||
}
|
||||
|
||||
type OpenVPNClient struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Address string `json:"address" yaml:"address"`
|
||||
Netmask string `json:"netmask" yaml:"netmask"`
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address"`
|
||||
Netmask string `json:"netmask"`
|
||||
}
|
||||
|
||||
func DefaultOpenVPN() *OpenVPN {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package config
|
||||
|
||||
type Password struct {
|
||||
Network string `json:"network,omitempty" yaml:"network,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
@@ -9,36 +9,36 @@ import (
|
||||
)
|
||||
|
||||
type Interface struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
IPMtu int `json:"mtu,omitempty" yaml:"mtu,omitempty"`
|
||||
Address string `json:"address,omitempty" yaml:"address,omitempty"`
|
||||
Bridge string `json:"bridge,omitempty" yaml:"bridge,omitempty"`
|
||||
Provider string `json:"provider,omitempty" yaml:"provider,omitempty"`
|
||||
Cost int `json:"cost,omitempty" yaml:"cost,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
IPMtu int `json:"mtu,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
Bridge string `json:"bridge,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Cost int `json:"cost,omitempty"`
|
||||
}
|
||||
|
||||
type Point struct {
|
||||
File string `json:"file,omitempty" yaml:"file,omitempty"`
|
||||
Alias string `json:"alias,omitempty" yaml:"alias,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
Connection string `json:"connection"`
|
||||
Timeout int `json:"timeout,omitempty" yaml:"timeout,omitempty"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Network string `json:"network,omitempty" yaml:"network,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
Interface Interface `json:"interface,omitempty" yaml:"interface,omitempty"`
|
||||
Log Log `json:"log,omitempty" yaml:"log,omitempty"`
|
||||
Http *Http `json:"http,omitempty" yaml:"http,omitempty"`
|
||||
Crypt *Crypt `json:"crypt,omitempty" yaml:"crypt,omitempty"`
|
||||
PProf string `json:"pprof,omitempty" yaml:"pprof,omitempty"`
|
||||
RequestAddr bool `json:"requestAddr,omitempty" yaml:"requestAddr,omitempty"`
|
||||
ByPass bool `json:"bypass,omitempty" yaml:"bypass,omitempty"`
|
||||
SaveFile string `json:"-" yaml:"-"`
|
||||
Queue *Queue `json:"queue,omitempty" yaml:"queue,omitempty"`
|
||||
Terminal string `json:"-" yaml:"-"`
|
||||
Cert *Cert `json:"cert,omitempty" yaml:"cert,omitempty"`
|
||||
StatusFile string `json:"status,omitempty" yaml:"status,omitempty"`
|
||||
PidFile string `json:"pid,omitempty" yaml:"pid,omitempty"`
|
||||
Interface Interface `json:"interface,omitempty"`
|
||||
Log Log `json:"log,omitempty"`
|
||||
Http *Http `json:"http,omitempty"`
|
||||
Crypt *Crypt `json:"crypt,omitempty"`
|
||||
PProf string `json:"pprof,omitempty"`
|
||||
RequestAddr bool `json:"requestAddr,omitempty"`
|
||||
ByPass bool `json:"bypass,omitempty"`
|
||||
SaveFile string `json:"-"`
|
||||
Queue *Queue `json:"queue,omitempty"`
|
||||
Terminal string `json:"-"`
|
||||
Cert *Cert `json:"cert,omitempty"`
|
||||
StatusFile string `json:"status,omitempty"`
|
||||
PidFile string `json:"pid,omitempty"`
|
||||
}
|
||||
|
||||
func DefaultPoint() *Point {
|
||||
|
@@ -11,7 +11,7 @@ type ShadowProxy struct {
|
||||
Cipher string `json:"cipher,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Plugin string `json:"plugin,omitempty"`
|
||||
PluginOpts string `json:"pluginOpts,omitempty" yaml:"pluginOpts,omitempty"`
|
||||
PluginOpts string `json:"pluginOpts,omitempty"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
}
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
package config
|
||||
|
||||
type IpSubnet struct {
|
||||
Network string `json:"network,omitempty" yaml:"network,omitempty"`
|
||||
Start string `json:"start,omitempty" yaml:"start,omitempty"`
|
||||
End string `json:"end,omitempty" yaml:"end,omitempty"`
|
||||
Netmask string `json:"netmask,omitempty" yaml:"netmask,omitempty"`
|
||||
type Subnet struct {
|
||||
Network string `json:"network,omitempty"`
|
||||
Start string `json:"startAt,omitempty"`
|
||||
End string `json:"endAt,omitempty"`
|
||||
Netmask string `json:"netmask,omitempty"`
|
||||
}
|
||||
|
||||
type MultiPath struct {
|
||||
@@ -13,17 +13,17 @@ type MultiPath struct {
|
||||
}
|
||||
|
||||
type PrefixRoute struct {
|
||||
File string `json:"-" yaml:"-"`
|
||||
Network string `json:"network,omitempty" yaml:"network,omitempty"`
|
||||
File string `json:"-"`
|
||||
Network string `json:"network,omitempty"`
|
||||
Prefix string `json:"prefix"`
|
||||
NextHop string `json:"nexthop"`
|
||||
MultiPath []MultiPath `json:"multipath,omitempty"`
|
||||
Metric int `json:"metric"`
|
||||
Mode string `json:"forward,omitempty" yaml:"forward,omitempty"` // route or snat
|
||||
Mode string `json:"forward,omitempty"` // route or snat
|
||||
}
|
||||
|
||||
type HostLease struct {
|
||||
Network string `json:"network,omitempty" yaml:"network,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
Hostname string `json:"hostname"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ func (p *Perf) Correct(obj *Perf) {
|
||||
type Switch struct {
|
||||
File string `json:"file"`
|
||||
Alias string `json:"alias"`
|
||||
Perf Perf `json:"limit,omitempty" yaml:"limit"`
|
||||
Perf Perf `json:"limit,omitempty"`
|
||||
Protocol string `json:"protocol"` // tcp, tls, udp, kcp, ws and wss.
|
||||
Listen string `json:"listen"`
|
||||
Timeout int `json:"timeout"`
|
||||
@@ -73,16 +73,16 @@ type Switch struct {
|
||||
Log Log `json:"log"`
|
||||
Cert *Cert `json:"cert,omitempty"`
|
||||
Crypt *Crypt `json:"crypt,omitempty"`
|
||||
Network []*Network `json:"network,omitempty" yaml:"network"`
|
||||
Acl []*ACL `json:"acl,omitempty" yaml:"acl,omitempty"`
|
||||
FireWall []FlowRule `json:"firewall,omitempty" yaml:"firewall,omitempty"`
|
||||
Inspect []string `json:"inspect,omitempty" yaml:"inspect,omitempty"`
|
||||
Queue Queue `json:"queue" yaml:"queue"`
|
||||
PassFile string `json:"password" yaml:"password"`
|
||||
Ldap *LDAP `json:"ldap,omitempty" yaml:"ldap,omitempty"`
|
||||
AddrPool string `json:"pool,omitempty" yaml:"pool,omitempty"`
|
||||
ConfDir string `json:"-" yaml:"-"`
|
||||
TokenFile string `json:"-" yaml:"-"`
|
||||
Network []*Network `json:"network,omitempty"`
|
||||
Acl []*ACL `json:"acl,omitempty"`
|
||||
FireWall []FlowRule `json:"firewall,omitempty"`
|
||||
Inspect []string `json:"inspect,omitempty"`
|
||||
Queue Queue `json:"queue"`
|
||||
PassFile string `json:"password"`
|
||||
Ldap *LDAP `json:"ldap,omitempty"`
|
||||
AddrPool string `json:"pool,omitempty"`
|
||||
ConfDir string `json:"-"`
|
||||
TokenFile string `json:"-"`
|
||||
}
|
||||
|
||||
func DefaultSwitch() *Switch {
|
||||
@@ -299,3 +299,12 @@ func (s *Switch) Reload() {
|
||||
obj.Reload()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Switch) GetNetwork(name string) *Network {
|
||||
for _, obj := range s.Network {
|
||||
if obj.Name == name {
|
||||
return obj
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package config
|
||||
|
||||
type VxLANSpecifies struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Vni uint32 `json:"vni"`
|
||||
Fabric string `json:"fabric"`
|
||||
}
|
||||
|
@@ -96,10 +96,12 @@ func SchemaToUserModel(user *schema.User) *User {
|
||||
func NewNetworkSchema(n *Network) schema.Network {
|
||||
sn := schema.Network{
|
||||
Name: n.Name,
|
||||
Subnet: schema.Subnet{
|
||||
IfAddr: n.IfAddr,
|
||||
IpStart: n.IpStart,
|
||||
IpEnd: n.IpEnd,
|
||||
Netmask: n.Netmask,
|
||||
},
|
||||
Routes: make([]schema.PrefixRoute, 0, 32),
|
||||
}
|
||||
for _, route := range n.Routes {
|
||||
|
@@ -16,11 +16,15 @@ type PrefixRoute struct {
|
||||
Mode string `json:"mode"`
|
||||
}
|
||||
|
||||
type Subnet struct {
|
||||
IfAddr string `json:"address,omitempty"`
|
||||
IpStart string `json:"startAt,omitempty"`
|
||||
IpEnd string `json:"endAt,omitempty"`
|
||||
Netmask string `json:"netmask"`
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
Name string `json:"name"`
|
||||
IfAddr string `json:"ifAddr,omitempty"`
|
||||
IpStart string `json:"ipStart,omitempty"`
|
||||
IpEnd string `json:"ipEnd,omitempty"`
|
||||
Netmask string `json:"netmask"`
|
||||
Subnet Subnet `json:"subnet"`
|
||||
Routes []PrefixRoute `json:"routes"`
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package schema
|
||||
|
||||
type OnLine struct {
|
||||
HitTime int64 `json:"hittime"`
|
||||
HitTime int64 `json:"aliveTime"`
|
||||
UpTime int64 `json:"uptime"`
|
||||
EthType uint16 `json:"ethType"`
|
||||
IpSource string `json:"ipSource"`
|
||||
IpDest string `json:"ipDestination"`
|
||||
IpProto string `json:"ipProtocol"`
|
||||
PortSource uint16 `json:"portSource"`
|
||||
PortDest uint16 `json:"portDestination"`
|
||||
IpSource string `json:"sourceAddr"`
|
||||
IpDest string `json:"destAddr"`
|
||||
IpProto string `json:"protocol"`
|
||||
PortSource uint16 `json:"sourcePort"`
|
||||
PortDest uint16 `json:"destPort"`
|
||||
}
|
||||
|
20
vendor/github.com/ghodss/yaml/.gitignore
generated
vendored
Normal file
20
vendor/github.com/ghodss/yaml/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# OSX leaves these everywhere on SMB shares
|
||||
._*
|
||||
|
||||
# Eclipse files
|
||||
.classpath
|
||||
.project
|
||||
.settings/**
|
||||
|
||||
# Emacs save files
|
||||
*~
|
||||
|
||||
# Vim-related files
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
|
||||
# Go test binaries
|
||||
*.test
|
7
vendor/github.com/ghodss/yaml/.travis.yml
generated
vendored
Normal file
7
vendor/github.com/ghodss/yaml/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
script:
|
||||
- go test
|
||||
- go build
|
50
vendor/github.com/ghodss/yaml/LICENSE
generated
vendored
Normal file
50
vendor/github.com/ghodss/yaml/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Sam Ghods
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
121
vendor/github.com/ghodss/yaml/README.md
generated
vendored
Normal file
121
vendor/github.com/ghodss/yaml/README.md
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
# YAML marshaling and unmarshaling support for Go
|
||||
|
||||
[](https://travis-ci.org/ghodss/yaml)
|
||||
|
||||
## Introduction
|
||||
|
||||
A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs.
|
||||
|
||||
In short, this library first converts YAML to JSON using go-yaml and then uses `json.Marshal` and `json.Unmarshal` to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods `MarshalJSON` and `UnmarshalJSON` unlike go-yaml. For a detailed overview of the rationale behind this method, [see this blog post](http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/).
|
||||
|
||||
## Compatibility
|
||||
|
||||
This package uses [go-yaml](https://github.com/go-yaml/yaml) and therefore supports [everything go-yaml supports](https://github.com/go-yaml/yaml#compatibility).
|
||||
|
||||
## Caveats
|
||||
|
||||
**Caveat #1:** When using `yaml.Marshal` and `yaml.Unmarshal`, binary data should NOT be preceded with the `!!binary` YAML tag. If you do, go-yaml will convert the binary data from base64 to native binary data, which is not compatible with JSON. You can still use binary in your YAML files though - just store them without the `!!binary` tag and decode the base64 in your code (e.g. in the custom JSON methods `MarshalJSON` and `UnmarshalJSON`). This also has the benefit that your YAML and your JSON binary data will be decoded exactly the same way. As an example:
|
||||
|
||||
```
|
||||
BAD:
|
||||
exampleKey: !!binary gIGC
|
||||
|
||||
GOOD:
|
||||
exampleKey: gIGC
|
||||
... and decode the base64 data in your code.
|
||||
```
|
||||
|
||||
**Caveat #2:** When using `YAMLToJSON` directly, maps with keys that are maps will result in an error since this is not supported by JSON. This error will occur in `Unmarshal` as well since you can't unmarshal map keys anyways since struct fields can't be keys.
|
||||
|
||||
## Installation and usage
|
||||
|
||||
To install, run:
|
||||
|
||||
```
|
||||
$ go get github.com/ghodss/yaml
|
||||
```
|
||||
|
||||
And import using:
|
||||
|
||||
```
|
||||
import "github.com/ghodss/yaml"
|
||||
```
|
||||
|
||||
Usage is very similar to the JSON library:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
type Person struct {
|
||||
Name string `json:"name"` // Affects YAML field names too.
|
||||
Age int `json:"age"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Marshal a Person struct to YAML.
|
||||
p := Person{"John", 30}
|
||||
y, err := yaml.Marshal(p)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(y))
|
||||
/* Output:
|
||||
age: 30
|
||||
name: John
|
||||
*/
|
||||
|
||||
// Unmarshal the YAML back into a Person struct.
|
||||
var p2 Person
|
||||
err = yaml.Unmarshal(y, &p2)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(p2)
|
||||
/* Output:
|
||||
{John 30}
|
||||
*/
|
||||
}
|
||||
```
|
||||
|
||||
`yaml.YAMLToJSON` and `yaml.JSONToYAML` methods are also available:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
j := []byte(`{"name": "John", "age": 30}`)
|
||||
y, err := yaml.JSONToYAML(j)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(y))
|
||||
/* Output:
|
||||
name: John
|
||||
age: 30
|
||||
*/
|
||||
j2, err := yaml.YAMLToJSON(y)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(j2))
|
||||
/* Output:
|
||||
{"age":30,"name":"John"}
|
||||
*/
|
||||
}
|
||||
```
|
501
vendor/github.com/ghodss/yaml/fields.go
generated
vendored
Normal file
501
vendor/github.com/ghodss/yaml/fields.go
generated
vendored
Normal file
@@ -0,0 +1,501 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// indirect walks down v allocating pointers as needed,
|
||||
// until it gets to a non-pointer.
|
||||
// if it encounters an Unmarshaler, indirect stops and returns that.
|
||||
// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
|
||||
func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
|
||||
// If v is a named type and is addressable,
|
||||
// start with its address, so that if the type has pointer methods,
|
||||
// we find them.
|
||||
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
for {
|
||||
// Load value from interface, but only if the result will be
|
||||
// usefully addressable.
|
||||
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||
e := v.Elem()
|
||||
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||
v = e
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Ptr {
|
||||
break
|
||||
}
|
||||
|
||||
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
|
||||
break
|
||||
}
|
||||
if v.IsNil() {
|
||||
if v.CanSet() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
} else {
|
||||
v = reflect.New(v.Type().Elem())
|
||||
}
|
||||
}
|
||||
if v.Type().NumMethod() > 0 {
|
||||
if u, ok := v.Interface().(json.Unmarshaler); ok {
|
||||
return u, nil, reflect.Value{}
|
||||
}
|
||||
if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
|
||||
return nil, u, reflect.Value{}
|
||||
}
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
return nil, nil, v
|
||||
}
|
||||
|
||||
// A field represents a single field found in a struct.
|
||||
type field struct {
|
||||
name string
|
||||
nameBytes []byte // []byte(name)
|
||||
equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
|
||||
|
||||
tag bool
|
||||
index []int
|
||||
typ reflect.Type
|
||||
omitEmpty bool
|
||||
quoted bool
|
||||
}
|
||||
|
||||
func fillField(f field) field {
|
||||
f.nameBytes = []byte(f.name)
|
||||
f.equalFold = foldFunc(f.nameBytes)
|
||||
return f
|
||||
}
|
||||
|
||||
// byName sorts field by name, breaking ties with depth,
|
||||
// then breaking ties with "name came from json tag", then
|
||||
// breaking ties with index sequence.
|
||||
type byName []field
|
||||
|
||||
func (x byName) Len() int { return len(x) }
|
||||
|
||||
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byName) Less(i, j int) bool {
|
||||
if x[i].name != x[j].name {
|
||||
return x[i].name < x[j].name
|
||||
}
|
||||
if len(x[i].index) != len(x[j].index) {
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
if x[i].tag != x[j].tag {
|
||||
return x[i].tag
|
||||
}
|
||||
return byIndex(x).Less(i, j)
|
||||
}
|
||||
|
||||
// byIndex sorts field by index sequence.
|
||||
type byIndex []field
|
||||
|
||||
func (x byIndex) Len() int { return len(x) }
|
||||
|
||||
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byIndex) Less(i, j int) bool {
|
||||
for k, xik := range x[i].index {
|
||||
if k >= len(x[j].index) {
|
||||
return false
|
||||
}
|
||||
if xik != x[j].index[k] {
|
||||
return xik < x[j].index[k]
|
||||
}
|
||||
}
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
|
||||
// typeFields returns a list of fields that JSON should recognize for the given type.
|
||||
// The algorithm is breadth-first search over the set of structs to include - the top struct
|
||||
// and then any reachable anonymous structs.
|
||||
func typeFields(t reflect.Type) []field {
|
||||
// Anonymous fields to explore at the current level and the next.
|
||||
current := []field{}
|
||||
next := []field{{typ: t}}
|
||||
|
||||
// Count of queued names for current level and the next.
|
||||
count := map[reflect.Type]int{}
|
||||
nextCount := map[reflect.Type]int{}
|
||||
|
||||
// Types already visited at an earlier level.
|
||||
visited := map[reflect.Type]bool{}
|
||||
|
||||
// Fields found.
|
||||
var fields []field
|
||||
|
||||
for len(next) > 0 {
|
||||
current, next = next, current[:0]
|
||||
count, nextCount = nextCount, map[reflect.Type]int{}
|
||||
|
||||
for _, f := range current {
|
||||
if visited[f.typ] {
|
||||
continue
|
||||
}
|
||||
visited[f.typ] = true
|
||||
|
||||
// Scan f.typ for fields to include.
|
||||
for i := 0; i < f.typ.NumField(); i++ {
|
||||
sf := f.typ.Field(i)
|
||||
if sf.PkgPath != "" { // unexported
|
||||
continue
|
||||
}
|
||||
tag := sf.Tag.Get("json")
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
name, opts := parseTag(tag)
|
||||
if !isValidTag(name) {
|
||||
name = ""
|
||||
}
|
||||
index := make([]int, len(f.index)+1)
|
||||
copy(index, f.index)
|
||||
index[len(f.index)] = i
|
||||
|
||||
ft := sf.Type
|
||||
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
|
||||
// Follow pointer.
|
||||
ft = ft.Elem()
|
||||
}
|
||||
|
||||
// Record found field and index sequence.
|
||||
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
tagged := name != ""
|
||||
if name == "" {
|
||||
name = sf.Name
|
||||
}
|
||||
fields = append(fields, fillField(field{
|
||||
name: name,
|
||||
tag: tagged,
|
||||
index: index,
|
||||
typ: ft,
|
||||
omitEmpty: opts.Contains("omitempty"),
|
||||
quoted: opts.Contains("string"),
|
||||
}))
|
||||
if count[f.typ] > 1 {
|
||||
// If there were multiple instances, add a second,
|
||||
// so that the annihilation code will see a duplicate.
|
||||
// It only cares about the distinction between 1 or 2,
|
||||
// so don't bother generating any more copies.
|
||||
fields = append(fields, fields[len(fields)-1])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Record new anonymous struct to explore in next round.
|
||||
nextCount[ft]++
|
||||
if nextCount[ft] == 1 {
|
||||
next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(byName(fields))
|
||||
|
||||
// Delete all fields that are hidden by the Go rules for embedded fields,
|
||||
// except that fields with JSON tags are promoted.
|
||||
|
||||
// The fields are sorted in primary order of name, secondary order
|
||||
// of field index length. Loop over names; for each name, delete
|
||||
// hidden fields by choosing the one dominant field that survives.
|
||||
out := fields[:0]
|
||||
for advance, i := 0, 0; i < len(fields); i += advance {
|
||||
// One iteration per name.
|
||||
// Find the sequence of fields with the name of this first field.
|
||||
fi := fields[i]
|
||||
name := fi.name
|
||||
for advance = 1; i+advance < len(fields); advance++ {
|
||||
fj := fields[i+advance]
|
||||
if fj.name != name {
|
||||
break
|
||||
}
|
||||
}
|
||||
if advance == 1 { // Only one field with this name
|
||||
out = append(out, fi)
|
||||
continue
|
||||
}
|
||||
dominant, ok := dominantField(fields[i : i+advance])
|
||||
if ok {
|
||||
out = append(out, dominant)
|
||||
}
|
||||
}
|
||||
|
||||
fields = out
|
||||
sort.Sort(byIndex(fields))
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// dominantField looks through the fields, all of which are known to
|
||||
// have the same name, to find the single field that dominates the
|
||||
// others using Go's embedding rules, modified by the presence of
|
||||
// JSON tags. If there are multiple top-level fields, the boolean
|
||||
// will be false: This condition is an error in Go and we skip all
|
||||
// the fields.
|
||||
func dominantField(fields []field) (field, bool) {
|
||||
// The fields are sorted in increasing index-length order. The winner
|
||||
// must therefore be one with the shortest index length. Drop all
|
||||
// longer entries, which is easy: just truncate the slice.
|
||||
length := len(fields[0].index)
|
||||
tagged := -1 // Index of first tagged field.
|
||||
for i, f := range fields {
|
||||
if len(f.index) > length {
|
||||
fields = fields[:i]
|
||||
break
|
||||
}
|
||||
if f.tag {
|
||||
if tagged >= 0 {
|
||||
// Multiple tagged fields at the same level: conflict.
|
||||
// Return no field.
|
||||
return field{}, false
|
||||
}
|
||||
tagged = i
|
||||
}
|
||||
}
|
||||
if tagged >= 0 {
|
||||
return fields[tagged], true
|
||||
}
|
||||
// All remaining fields have the same length. If there's more than one,
|
||||
// we have a conflict (two fields named "X" at the same level) and we
|
||||
// return no field.
|
||||
if len(fields) > 1 {
|
||||
return field{}, false
|
||||
}
|
||||
return fields[0], true
|
||||
}
|
||||
|
||||
var fieldCache struct {
|
||||
sync.RWMutex
|
||||
m map[reflect.Type][]field
|
||||
}
|
||||
|
||||
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
|
||||
func cachedTypeFields(t reflect.Type) []field {
|
||||
fieldCache.RLock()
|
||||
f := fieldCache.m[t]
|
||||
fieldCache.RUnlock()
|
||||
if f != nil {
|
||||
return f
|
||||
}
|
||||
|
||||
// Compute fields without lock.
|
||||
// Might duplicate effort but won't hold other computations back.
|
||||
f = typeFields(t)
|
||||
if f == nil {
|
||||
f = []field{}
|
||||
}
|
||||
|
||||
fieldCache.Lock()
|
||||
if fieldCache.m == nil {
|
||||
fieldCache.m = map[reflect.Type][]field{}
|
||||
}
|
||||
fieldCache.m[t] = f
|
||||
fieldCache.Unlock()
|
||||
return f
|
||||
}
|
||||
|
||||
func isValidTag(s string) bool {
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
for _, c := range s {
|
||||
switch {
|
||||
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
|
||||
// Backslash and quote chars are reserved, but
|
||||
// otherwise any punctuation chars are allowed
|
||||
// in a tag name.
|
||||
default:
|
||||
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const (
|
||||
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
|
||||
kelvin = '\u212a'
|
||||
smallLongEss = '\u017f'
|
||||
)
|
||||
|
||||
// foldFunc returns one of four different case folding equivalence
|
||||
// functions, from most general (and slow) to fastest:
|
||||
//
|
||||
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
|
||||
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
|
||||
// 3) asciiEqualFold, no special, but includes non-letters (including _)
|
||||
// 4) simpleLetterEqualFold, no specials, no non-letters.
|
||||
//
|
||||
// The letters S and K are special because they map to 3 runes, not just 2:
|
||||
// * S maps to s and to U+017F 'ſ' Latin small letter long s
|
||||
// * k maps to K and to U+212A 'K' Kelvin sign
|
||||
// See http://play.golang.org/p/tTxjOc0OGo
|
||||
//
|
||||
// The returned function is specialized for matching against s and
|
||||
// should only be given s. It's not curried for performance reasons.
|
||||
func foldFunc(s []byte) func(s, t []byte) bool {
|
||||
nonLetter := false
|
||||
special := false // special letter
|
||||
for _, b := range s {
|
||||
if b >= utf8.RuneSelf {
|
||||
return bytes.EqualFold
|
||||
}
|
||||
upper := b & caseMask
|
||||
if upper < 'A' || upper > 'Z' {
|
||||
nonLetter = true
|
||||
} else if upper == 'K' || upper == 'S' {
|
||||
// See above for why these letters are special.
|
||||
special = true
|
||||
}
|
||||
}
|
||||
if special {
|
||||
return equalFoldRight
|
||||
}
|
||||
if nonLetter {
|
||||
return asciiEqualFold
|
||||
}
|
||||
return simpleLetterEqualFold
|
||||
}
|
||||
|
||||
// equalFoldRight is a specialization of bytes.EqualFold when s is
|
||||
// known to be all ASCII (including punctuation), but contains an 's',
|
||||
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
|
||||
// See comments on foldFunc.
|
||||
func equalFoldRight(s, t []byte) bool {
|
||||
for _, sb := range s {
|
||||
if len(t) == 0 {
|
||||
return false
|
||||
}
|
||||
tb := t[0]
|
||||
if tb < utf8.RuneSelf {
|
||||
if sb != tb {
|
||||
sbUpper := sb & caseMask
|
||||
if 'A' <= sbUpper && sbUpper <= 'Z' {
|
||||
if sbUpper != tb&caseMask {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
t = t[1:]
|
||||
continue
|
||||
}
|
||||
// sb is ASCII and t is not. t must be either kelvin
|
||||
// sign or long s; sb must be s, S, k, or K.
|
||||
tr, size := utf8.DecodeRune(t)
|
||||
switch sb {
|
||||
case 's', 'S':
|
||||
if tr != smallLongEss {
|
||||
return false
|
||||
}
|
||||
case 'k', 'K':
|
||||
if tr != kelvin {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
t = t[size:]
|
||||
|
||||
}
|
||||
if len(t) > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// asciiEqualFold is a specialization of bytes.EqualFold for use when
|
||||
// s is all ASCII (but may contain non-letters) and contains no
|
||||
// special-folding letters.
|
||||
// See comments on foldFunc.
|
||||
func asciiEqualFold(s, t []byte) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for i, sb := range s {
|
||||
tb := t[i]
|
||||
if sb == tb {
|
||||
continue
|
||||
}
|
||||
if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
|
||||
if sb&caseMask != tb&caseMask {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// simpleLetterEqualFold is a specialization of bytes.EqualFold for
|
||||
// use when s is all ASCII letters (no underscores, etc) and also
|
||||
// doesn't contain 'k', 'K', 's', or 'S'.
|
||||
// See comments on foldFunc.
|
||||
func simpleLetterEqualFold(s, t []byte) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for i, b := range s {
|
||||
if b&caseMask != t[i]&caseMask {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type tagOptions string
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
277
vendor/github.com/ghodss/yaml/yaml.go
generated
vendored
Normal file
277
vendor/github.com/ghodss/yaml/yaml.go
generated
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Marshals the object into JSON then converts JSON to YAML and returns the
|
||||
// YAML.
|
||||
func Marshal(o interface{}) ([]byte, error) {
|
||||
j, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling into JSON: %v", err)
|
||||
}
|
||||
|
||||
y, err := JSONToYAML(j)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting JSON to YAML: %v", err)
|
||||
}
|
||||
|
||||
return y, nil
|
||||
}
|
||||
|
||||
// Converts YAML to JSON then uses JSON to unmarshal into an object.
|
||||
func Unmarshal(y []byte, o interface{}) error {
|
||||
vo := reflect.ValueOf(o)
|
||||
j, err := yamlToJSON(y, &vo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error converting YAML to JSON: %v", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(j, o)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unmarshaling JSON: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert JSON to YAML.
|
||||
func JSONToYAML(j []byte) ([]byte, error) {
|
||||
// Convert the JSON to an object.
|
||||
var jsonObj interface{}
|
||||
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
|
||||
// Go JSON library doesn't try to pick the right number type (int, float,
|
||||
// etc.) when unmarshalling to interface{}, it just picks float64
|
||||
// universally. go-yaml does go through the effort of picking the right
|
||||
// number type, so we can preserve number type throughout this process.
|
||||
err := yaml.Unmarshal(j, &jsonObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Marshal this object into YAML.
|
||||
return yaml.Marshal(jsonObj)
|
||||
}
|
||||
|
||||
// Convert YAML to JSON. Since JSON is a subset of YAML, passing JSON through
|
||||
// this method should be a no-op.
|
||||
//
|
||||
// Things YAML can do that are not supported by JSON:
|
||||
// * In YAML you can have binary and null keys in your maps. These are invalid
|
||||
// in JSON. (int and float keys are converted to strings.)
|
||||
// * Binary data in YAML with the !!binary tag is not supported. If you want to
|
||||
// use binary data with this library, encode the data as base64 as usual but do
|
||||
// not use the !!binary tag in your YAML. This will ensure the original base64
|
||||
// encoded data makes it all the way through to the JSON.
|
||||
func YAMLToJSON(y []byte) ([]byte, error) {
|
||||
return yamlToJSON(y, nil)
|
||||
}
|
||||
|
||||
func yamlToJSON(y []byte, jsonTarget *reflect.Value) ([]byte, error) {
|
||||
// Convert the YAML to an object.
|
||||
var yamlObj interface{}
|
||||
err := yaml.Unmarshal(y, &yamlObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// YAML objects are not completely compatible with JSON objects (e.g. you
|
||||
// can have non-string keys in YAML). So, convert the YAML-compatible object
|
||||
// to a JSON-compatible object, failing with an error if irrecoverable
|
||||
// incompatibilties happen along the way.
|
||||
jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert this object to JSON and return the data.
|
||||
return json.Marshal(jsonObj)
|
||||
}
|
||||
|
||||
func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (interface{}, error) {
|
||||
var err error
|
||||
|
||||
// Resolve jsonTarget to a concrete value (i.e. not a pointer or an
|
||||
// interface). We pass decodingNull as false because we're not actually
|
||||
// decoding into the value, we're just checking if the ultimate target is a
|
||||
// string.
|
||||
if jsonTarget != nil {
|
||||
ju, tu, pv := indirect(*jsonTarget, false)
|
||||
// We have a JSON or Text Umarshaler at this level, so we can't be trying
|
||||
// to decode into a string.
|
||||
if ju != nil || tu != nil {
|
||||
jsonTarget = nil
|
||||
} else {
|
||||
jsonTarget = &pv
|
||||
}
|
||||
}
|
||||
|
||||
// If yamlObj is a number or a boolean, check if jsonTarget is a string -
|
||||
// if so, coerce. Else return normal.
|
||||
// If yamlObj is a map or array, find the field that each key is
|
||||
// unmarshaling to, and when you recurse pass the reflect.Value for that
|
||||
// field back into this function.
|
||||
switch typedYAMLObj := yamlObj.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
// JSON does not support arbitrary keys in a map, so we must convert
|
||||
// these keys to strings.
|
||||
//
|
||||
// From my reading of go-yaml v2 (specifically the resolve function),
|
||||
// keys can only have the types string, int, int64, float64, binary
|
||||
// (unsupported), or null (unsupported).
|
||||
strMap := make(map[string]interface{})
|
||||
for k, v := range typedYAMLObj {
|
||||
// Resolve the key to a string first.
|
||||
var keyString string
|
||||
switch typedKey := k.(type) {
|
||||
case string:
|
||||
keyString = typedKey
|
||||
case int:
|
||||
keyString = strconv.Itoa(typedKey)
|
||||
case int64:
|
||||
// go-yaml will only return an int64 as a key if the system
|
||||
// architecture is 32-bit and the key's value is between 32-bit
|
||||
// and 64-bit. Otherwise the key type will simply be int.
|
||||
keyString = strconv.FormatInt(typedKey, 10)
|
||||
case float64:
|
||||
// Stolen from go-yaml to use the same conversion to string as
|
||||
// the go-yaml library uses to convert float to string when
|
||||
// Marshaling.
|
||||
s := strconv.FormatFloat(typedKey, 'g', -1, 32)
|
||||
switch s {
|
||||
case "+Inf":
|
||||
s = ".inf"
|
||||
case "-Inf":
|
||||
s = "-.inf"
|
||||
case "NaN":
|
||||
s = ".nan"
|
||||
}
|
||||
keyString = s
|
||||
case bool:
|
||||
if typedKey {
|
||||
keyString = "true"
|
||||
} else {
|
||||
keyString = "false"
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v",
|
||||
reflect.TypeOf(k), k, v)
|
||||
}
|
||||
|
||||
// jsonTarget should be a struct or a map. If it's a struct, find
|
||||
// the field it's going to map to and pass its reflect.Value. If
|
||||
// it's a map, find the element type of the map and pass the
|
||||
// reflect.Value created from that type. If it's neither, just pass
|
||||
// nil - JSON conversion will error for us if it's a real issue.
|
||||
if jsonTarget != nil {
|
||||
t := *jsonTarget
|
||||
if t.Kind() == reflect.Struct {
|
||||
keyBytes := []byte(keyString)
|
||||
// Find the field that the JSON library would use.
|
||||
var f *field
|
||||
fields := cachedTypeFields(t.Type())
|
||||
for i := range fields {
|
||||
ff := &fields[i]
|
||||
if bytes.Equal(ff.nameBytes, keyBytes) {
|
||||
f = ff
|
||||
break
|
||||
}
|
||||
// Do case-insensitive comparison.
|
||||
if f == nil && ff.equalFold(ff.nameBytes, keyBytes) {
|
||||
f = ff
|
||||
}
|
||||
}
|
||||
if f != nil {
|
||||
// Find the reflect.Value of the most preferential
|
||||
// struct field.
|
||||
jtf := t.Field(f.index[0])
|
||||
strMap[keyString], err = convertToJSONableObject(v, &jtf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
} else if t.Kind() == reflect.Map {
|
||||
// Create a zero value of the map's element type to use as
|
||||
// the JSON target.
|
||||
jtv := reflect.Zero(t.Type().Elem())
|
||||
strMap[keyString], err = convertToJSONableObject(v, &jtv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
strMap[keyString], err = convertToJSONableObject(v, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return strMap, nil
|
||||
case []interface{}:
|
||||
// We need to recurse into arrays in case there are any
|
||||
// map[interface{}]interface{}'s inside and to convert any
|
||||
// numbers to strings.
|
||||
|
||||
// If jsonTarget is a slice (which it really should be), find the
|
||||
// thing it's going to map to. If it's not a slice, just pass nil
|
||||
// - JSON conversion will error for us if it's a real issue.
|
||||
var jsonSliceElemValue *reflect.Value
|
||||
if jsonTarget != nil {
|
||||
t := *jsonTarget
|
||||
if t.Kind() == reflect.Slice {
|
||||
// By default slices point to nil, but we need a reflect.Value
|
||||
// pointing to a value of the slice type, so we create one here.
|
||||
ev := reflect.Indirect(reflect.New(t.Type().Elem()))
|
||||
jsonSliceElemValue = &ev
|
||||
}
|
||||
}
|
||||
|
||||
// Make and use a new array.
|
||||
arr := make([]interface{}, len(typedYAMLObj))
|
||||
for i, v := range typedYAMLObj {
|
||||
arr[i], err = convertToJSONableObject(v, jsonSliceElemValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return arr, nil
|
||||
default:
|
||||
// If the target type is a string and the YAML type is a number,
|
||||
// convert the YAML type to a string.
|
||||
if jsonTarget != nil && (*jsonTarget).Kind() == reflect.String {
|
||||
// Based on my reading of go-yaml, it may return int, int64,
|
||||
// float64, or uint64.
|
||||
var s string
|
||||
switch typedVal := typedYAMLObj.(type) {
|
||||
case int:
|
||||
s = strconv.FormatInt(int64(typedVal), 10)
|
||||
case int64:
|
||||
s = strconv.FormatInt(typedVal, 10)
|
||||
case float64:
|
||||
s = strconv.FormatFloat(typedVal, 'g', -1, 32)
|
||||
case uint64:
|
||||
s = strconv.FormatUint(typedVal, 10)
|
||||
case bool:
|
||||
if typedVal {
|
||||
s = "true"
|
||||
} else {
|
||||
s = "false"
|
||||
}
|
||||
}
|
||||
if len(s) > 0 {
|
||||
yamlObj = interface{}(s)
|
||||
}
|
||||
}
|
||||
return yamlObj, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@@ -34,6 +34,9 @@ github.com/danieldin95/go-openvswitch/ovs
|
||||
github.com/davecgh/go-spew/spew
|
||||
# github.com/docker/libnetwork v0.5.6
|
||||
## explicit
|
||||
# github.com/ghodss/yaml v1.0.0
|
||||
## explicit
|
||||
github.com/ghodss/yaml
|
||||
# github.com/go-ldap/ldap v3.0.3+incompatible
|
||||
## explicit
|
||||
github.com/go-ldap/ldap
|
||||
|
Reference in New Issue
Block a user