Skip to content

Commit

Permalink
feat: add NewWatcherWithConfig() (#25)
Browse files Browse the repository at this point in the history
* feat: Added configuration-based constructors

* fix: keyName is not specified.

* test: new test for NewWatcherWithConfig()

* doc: NewWatcherWithConfig() usage
  • Loading branch information
yuetchn authored Jan 26, 2024
1 parent fcbdc9d commit ace56e7
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 0 deletions.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,49 @@ func main() {
}
```

## Simple Example(Configuration Mode)

```go
package main

import (
"log"

casbin "github.com/casbin/casbin/v2"
etcdwatcher "github.com/casbin/etcd-watcher/v2"
)

func updateCallback(rev string) {
log.Println("New revision detected:", rev)
}

func main() {
// Initialize the watcher.
// Use the configuration file as the parameter
w, _ := etcdwatcher.NewWatcherWithConfig(etcdwatcher.WatcherConfig{
Hosts: []string{"http://127.0.0.1:2379"},
Key: "/casbin",
User: "root",
Pass: "123",
})

// Initialize the enforcer.
e, _ := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

// Set the watcher for the enforcer.
e.SetWatcher(w)

// By default, the watcher's callback is automatically set to the
// enforcer's LoadPolicy() in the SetWatcher() call.
// We can change it by explicitly setting a callback.
w.SetUpdateCallback(updateCallback)

// Update the policy to test the effect.
// You should see "[New revision detected: X]" in the log.
e.SavePolicy()
}
```

## Getting Help

- [Casbin](https://github.com/casbin/casbin)
Expand Down
45 changes: 45 additions & 0 deletions watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ type Watcher struct {
keyName string
password string
lastSentRev int64
conf *WatcherConfig
}

type WatcherConfig struct {
Hosts []string
Key string `json:",default=casbin_watcher"`
User string
Pass string
DialKeepAliveTimeout time.Duration `json:",default=10"`
DialTimeout time.Duration `json:",default=30"`
}

// finalizer is the destructor for Watcher.
Expand Down Expand Up @@ -70,6 +80,30 @@ func NewWatcher(endpoints []string, keyName string, password ...string) (persist
return w, nil
}

// NewWatcherWithConfig is a configurable Watcher constructor
func NewWatcherWithConfig(config WatcherConfig) (persist.Watcher, error) {
w := &Watcher{}
w.running = true
w.callback = nil
w.keyName = config.Key
w.conf = &config

// Create the client.
err := w.createClient()
if err != nil {
return nil, err
}

// Call the destructor when the object is released.
runtime.SetFinalizer(w, finalizer)

go func() {
_ = w.startWatch()
}()

return w, nil
}

// Close closes the Watcher.
func (w *Watcher) Close() {
finalizer(w)
Expand All @@ -84,6 +118,17 @@ func (w *Watcher) createClient() error {
Password: w.password,
}

if w.conf != nil {
cfg = client.Config{
Endpoints: w.conf.Hosts,
// set timeout per request to fail fast when the target endpoints is unavailable
DialTimeout: time.Second * w.conf.DialTimeout,
DialKeepAliveTimeout: time.Second * w.conf.DialKeepAliveTimeout,
Username: w.conf.User,
Password: w.conf.Pass,
}
}

c, err := client.New(cfg)
if err != nil {
return err
Expand Down
12 changes: 12 additions & 0 deletions watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ func TestWatcher(t *testing.T) {
// Use the endpoints of etcd cluster as parameter.
updater, _ := NewWatcher([]string{"http://127.0.0.1:2379"}, "/casbin")

withConfigUpdater, _ := NewWatcherWithConfig(WatcherConfig{
Hosts: []string{"http://127.0.0.1:2379"},
Key: "/casbin",
User: "",
Pass: "",
})

// listener represents any other Casbin enforcer instance that watches the change of policy in DB.
listener, _ := NewWatcher([]string{"http://127.0.0.1:2379"}, "/casbin")
// listener should set a callback that gets called when policy changes.
Expand All @@ -41,6 +48,11 @@ func TestWatcher(t *testing.T) {
panic(err)
}

err = withConfigUpdater.Update()
if err != nil {
panic(err)
}

// Now the listener's callback updateCallback() should be called,
// because it receives the notification of policy update.
// You should see "[New revision detected: X]" in the log.
Expand Down

0 comments on commit ace56e7

Please sign in to comment.