Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add file change watch #534

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ type Static struct {
type File struct {
NoRouteHTMLPath string
RoutesPath string
Interval time.Duration
}

type Consul struct {
Expand Down
3 changes: 3 additions & 0 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ var defaultConfig = &Config{
},
Timeout: 10 * time.Second,
Retry: 500 * time.Millisecond,
File: File{
Interval: 2 * time.Second,
},
},
Runtime: Runtime{
GOGC: 800,
Expand Down
1 change: 1 addition & 0 deletions config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ func load(cmdline, environ, envprefix []string, props *properties.Properties) (c
f.DurationVar(&cfg.Registry.Retry, "registry.retry", defaultConfig.Registry.Retry, "retry interval during startup")
f.StringVar(&cfg.Registry.File.RoutesPath, "registry.file.path", defaultConfig.Registry.File.RoutesPath, "path to file based routing table")
f.StringVar(&cfg.Registry.File.NoRouteHTMLPath, "registry.file.noroutehtmlpath", defaultConfig.Registry.File.NoRouteHTMLPath, "path to file for HTML returned when no route is found")
f.DurationVar(&cfg.Registry.File.Interval, "registry.file.interval", defaultConfig.Registry.File.Interval, "check file changed interval")
f.StringVar(&cfg.Registry.Static.Routes, "registry.static.routes", defaultConfig.Registry.Static.Routes, "static routes")
f.StringVar(&cfg.Registry.Static.NoRouteHTML, "registry.static.noroutehtml", defaultConfig.Registry.Static.NoRouteHTML, "HTML which is returned when no route is found")
f.StringVar(&cfg.Registry.Consul.Addr, "registry.consul.addr", defaultConfig.Registry.Consul.Addr, "address of the consul agent")
Expand Down
10 changes: 10 additions & 0 deletions docs/content/ref/registry.file.interval.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "registry.file.interval"
---

`registry.file.interval` configures check file changed interval time.


The default is

registry.file.interval = 2s
7 changes: 7 additions & 0 deletions docs/content/ref/registry.file.path.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ title: "registry.file.path"
`registry.file.path` configures a file based routing table.
The value configures the path to the file with the routing table.

#### Example
registry.file.path = /home/zjj/route.txt
file content like is
```
route add svc / http://1.2.3.4:5000/
route add svc /test http://1.2.3.4:5001/
```
The default is

registry.file.path =
5 changes: 5 additions & 0 deletions fabio.properties
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,11 @@
#
# registry.file.noroutehtmlpath =

# registry.file.interval configures check file changed interval time.
#
# The default is
#
# registry.file.interval = 2s

# registry.consul.addr configures the address of the consul agent to connect to.
#
Expand Down
85 changes: 69 additions & 16 deletions registry/file/backend.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,83 @@
// Package file implements a simple file based registry
// backend which reads the routes from a file once.
// backend which reads the routes from a file.
//file content like registry.static.routes = route add web-svc /test http://127.0.0.1:8082
//registry.file.path = /home/zjj/fabio.txt
//registry.file.noroutehtmlpath = /home/zjj/404.html
package file

import (
"io/ioutil"
"log"
"os"
"time"

"github.com/fabiolb/fabio/config"
"github.com/fabiolb/fabio/registry"
"github.com/fabiolb/fabio/registry/static"
)

type be struct {
cfg *config.File
routesData *filedata
noRouteHTMLData *filedata
}

func NewBackend(cfg *config.File) (registry.Backend, error) {
routes, err := ioutil.ReadFile(cfg.RoutesPath)
if err != nil {
log.Println("[ERROR] Cannot read routes from ", cfg.RoutesPath)
return nil, err
}
noroutehtml, err := ioutil.ReadFile(cfg.NoRouteHTMLPath)
if err != nil {
log.Println("[ERROR] Cannot read no route HTML from ", cfg.NoRouteHTMLPath)
if _, err := os.Stat(cfg.RoutesPath); err != nil {
return nil, err
}
staticCfg := &config.Static{
NoRouteHTML: string(noroutehtml),
Routes: string(routes),

b := &be{cfg: cfg, routesData: &filedata{path: cfg.RoutesPath}, noRouteHTMLData: &filedata{path: cfg.NoRouteHTMLPath}}
return b, nil
}

func (b *be) Register(services []string) error {
return nil
}

func (b *be) Deregister(serviceName string) error {
return nil
}

func (b *be) DeregisterAll() error {
return nil
}

func (b *be) ManualPaths() ([]string, error) {
return nil, nil
}

func (b *be) ReadManual(string) (value string, version uint64, err error) {
return "", 0, nil
}

func (b *be) WriteManual(path string, value string, version uint64) (ok bool, err error) {
return false, nil
}

func (b *be) WatchServices() chan string {
ch := make(chan string)
go func() {
for {
readFile(b.routesData)
ch <- b.routesData.content
time.Sleep(b.cfg.Interval)
}
}()
return ch
}

func (b *be) WatchManual() chan string {
return make(chan string)
}

func (b *be) WatchNoRouteHTML() chan string {
ch := make(chan string)
if b.noRouteHTMLData.path != "" {
go func() {
for {
readFile(b.noRouteHTMLData)
ch <- b.noRouteHTMLData.content
time.Sleep(b.cfg.Interval)
}
}()
}
return static.NewBackend(staticCfg)
return ch
}
38 changes: 38 additions & 0 deletions registry/file/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package file

import (
"io/ioutil"
"log"
"os"
"time"
)

//file data
type filedata struct {
path string
content string
mtime time.Time
}

// Example
// file := &filedata{path:"/home/zjj/routes.txt"}
// err := readFile(file)
func readFile(file *filedata) error {
finfo, err := os.Stat(file.path)
if err != nil {
log.Println("[ERROR] Cannot read file stats() from ", file.path)
return err
}

lastmtime := finfo.ModTime()
if file.mtime != lastmtime {
data, err := ioutil.ReadFile(file.path)
if err != nil {
log.Println("[ERROR] Cannot read file data from ", file.path)
return err
}
file.content = string(data)
file.mtime = lastmtime
}
return nil
}