Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions cmd/gokc/gokc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/json"
"flag"
"fmt"
"os"
Expand Down Expand Up @@ -35,11 +36,15 @@ func init() {
}

func main() {
var filepath string
var isVersion bool
var (
filepath string
isVersion bool
printJSON bool
)
flag.StringVar(&filepath, "f", "/etc/keepalived/keepalived.conf", "keepalived.conf file path")
flag.BoolVar(&isVersion, "v", false, "print the version")
flag.BoolVar(&log.IsVerbose, "V", false, "verbose log mode")
flag.BoolVar(&printJSON, "json", false, "print configuration as json")
flag.Parse()

if isVersion {
Expand All @@ -57,14 +62,24 @@ func main() {
}
defer file.Close()

if err := parser.Parse(file, filepath); err != nil {
result, err := parser.Parse(file, filepath)
if err != nil {
if e, ok := err.(*parser.Error); ok {
msg := colorstring.Color(fmt.Sprintf("[white]%s:%d:%d: [red]%s[reset]", e.Filename, e.Line, e.Column, e.Message))
log.Error(msg)
} else {
log.Error(err)
}
}
log.Debugf("%#v\n", result)

log.Infof("gokc: the configuration file %s syntax is ok", filepath)
if printJSON {
j, err := json.Marshal(result)
if err != nil {
log.Error(err)
}
fmt.Println(string(j))
} else {
log.Infof("gokc: the configuration file %s syntax is ok", filepath)
}
}
50 changes: 50 additions & 0 deletions parser/ast.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package parser

// Token represents the token of the configuration.
type Token struct {
tok int
lit string
filename string
line int
column int
}

type Configuration struct {
Blocks []BlockAny
}

type BlockAny interface{} //FIXME

type Block struct {
name string // <STRING>: vrrp_script <STRING> { ... }
stmts []StmtAny
}

type BlockArgs struct { // virtual_server <IP ADDRESS> <PORT> { }
Name string `json:"name"`
Args []string `json:"args"`
Stmts []StmtAny `json:"stmts"`
}

type SubBlockArgs BlockArgs // real_server <IP ADDRESS> <PORT> { ... }

type StmtAny interface{} //FIXME

type Stmt struct { // state: MASTER
Key string `json:"key"`
Val Value `json:"value"`
}

type StmtMulti struct { // virtual_ipaddress { vips }
Key string `json:"key"`
Vals []Value `json:"values"`
}

type StmtValue = Value // static_ipaddress { address_options }

type Value interface{}

// VIPAddr represents virtual_ipaddress
type VIPAddr struct {
Addr string `json:"addr"`
}
21 changes: 21 additions & 0 deletions parser/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package parser

import "encoding/json"

func (conf Configuration) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Blocks []BlockAny `json:"blocks"`
}{
Blocks: conf.Blocks,
})
}

func (b Block) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Name string `json:"name"`
Stmts []StmtAny `json:"stmts"`
}{
Name: b.name,
Stmts: b.stmts,
})
}
22 changes: 9 additions & 13 deletions parser/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ func (t *Tokenizer) NextAll() ([]*Token, error) {
}

result = append(result, &Token{
value: token,
tok: token,
lit: s,
filename: t.filename,
line: t.scanner.Line,
column: t.scanner.Column,
Expand Down Expand Up @@ -332,17 +333,11 @@ func (t *Tokenizer) scanInclude(rawfilename string) ([]*Token, error) {
return result, nil
}

type Token struct {
value int
filename string
line int
column int
}

type Lexer struct {
tokens []*Token
pos int
e error
result []BlockAny
}

type Error struct {
Expand Down Expand Up @@ -378,7 +373,8 @@ func (l *Lexer) Lex(lval *yySymType) int {
return EOF
}
token := l.nextToken()
return token.value
lval.token = *token
return token.tok
}

func (l *Lexer) Error(msg string) {
Expand All @@ -391,16 +387,16 @@ func (l *Lexer) Error(msg string) {
}
}

func Parse(src io.Reader, filename string) error {
func Parse(src io.Reader, filename string) (Configuration, error) {
yyErrorVerbose = true
t := NewTokenizer(src, filename)
tokens, err := t.NextAll()
if err != nil {
return err
return Configuration{}, err
}
l := NewLexer(tokens)
if ret := yyParse(l); ret != 0 {
return l.e
return Configuration{}, l.e
}
return l.e
return Configuration{Blocks: l.result}, l.e
}
4 changes: 2 additions & 2 deletions parser/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func TestTokenizer_NextAll(t *testing.T) {
}
fmt.Printf("%+v", len(tokens))
for i, token := range tokens {
got, want := token.value, tt.toks[i]
got, want := token.tok, tt.toks[i]
if got != want {
t.Errorf("token got %v, want %v (%v)", got, want, i)
}
Expand All @@ -67,7 +67,7 @@ func TestTokenizer_NextAll(t *testing.T) {

func TestNewLexer(t *testing.T) {
tokens := []*Token{
{VRRP_INSTANCE, "dummy.conf", 2, 10},
{VRRP_INSTANCE, "vrrp_instance", "dummy.conf", 2, 10},
}
l := NewLexer(tokens)
if !reflect.DeepEqual(l.tokens, tokens) {
Expand Down
Loading