mirror of
https://github.com/cuigh/swirl
synced 2024-12-28 14:51:57 +00:00
Add ‘bolt’ storage engine
This commit is contained in:
parent
a7a4be4d71
commit
4ad92f6c73
14
Gopkg.lock
generated
14
Gopkg.lock
generated
@ -19,6 +19,13 @@
|
||||
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
|
||||
version = "v0.4.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/boltdb/bolt"
|
||||
packages = ["."]
|
||||
revision = "48ea1b39c25fc1bab3506fbc712ecbaa842c4d2d"
|
||||
source = "https://github.com/coreos/bbolt.git"
|
||||
version = "v1.3.1-coreos.6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/cuigh/auxo"
|
||||
@ -208,7 +215,10 @@
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["windows"]
|
||||
packages = [
|
||||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "2f57af4873d00d535c5c9028850aa2152e6a5566"
|
||||
|
||||
[[projects]]
|
||||
@ -226,6 +236,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "dea823c7646b8b71101e0443b1c0c36a723989261f733ad4cb44c6e9b0d3942d"
|
||||
inputs-digest = "fe9c254e0c7e739370b6380ed53816426b8245a1610db2cfc612aec63aa01701"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
@ -39,4 +39,9 @@ required = ["github.com/docker/distribution"]
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/docker/distribution"
|
||||
branch = "master"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/boltdb/bolt"
|
||||
source = "https://github.com/coreos/bbolt.git"
|
||||
version = "1.3.1-coreos.6"
|
||||
|
32
README.md
32
README.md
@ -75,7 +75,7 @@ Only these options can be set by environment variables for now.
|
||||
|
||||
| Name | Value |
|
||||
| --------------- | -----------------------------|
|
||||
| DB_TYPE | mongo |
|
||||
| DB_TYPE | mongo,bolt |
|
||||
| DB_ADDRESS | localhost:27017/swirl |
|
||||
| DOCKER_ENDPOINT | tcp://docker-proxy:2375 |
|
||||
| AUTH_TIMEOUT | 4h |
|
||||
@ -86,6 +86,8 @@ Docker support mounting configuration file through swarm from v17.06, so you can
|
||||
|
||||
## Deployment
|
||||
|
||||
Swirl support two storage engines now: mongo and bolt. **bolt** is suitable for develepment environment, **Swirl** can only deploy one replica if you use **bolt** storage engine.
|
||||
|
||||
### Stand alone
|
||||
|
||||
Just copy the swirl binary and config/assets/views directories to the host, and run it.
|
||||
@ -96,6 +98,19 @@ Just copy the swirl binary and config/assets/views directories to the host, and
|
||||
|
||||
### Docker
|
||||
|
||||
* Use **bolt** storage engine
|
||||
|
||||
```bash
|
||||
docker run -d -p 8001:8001 \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v /data/swirl:/data/swirl \
|
||||
-e DB_TYPE=bolt \
|
||||
--name=swirl \
|
||||
cuigh/swirl
|
||||
```
|
||||
|
||||
* Use **MongoDB** storage engine
|
||||
|
||||
```bash
|
||||
docker run -d -p 8001:8001 \
|
||||
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
|
||||
@ -107,6 +122,21 @@ docker run -d -p 8001:8001 \
|
||||
|
||||
### Docker swarm
|
||||
|
||||
* Use **bolt** storage engine
|
||||
|
||||
```bash
|
||||
docker service create \
|
||||
--name=swirl \
|
||||
--publish=8001:8001/tcp \
|
||||
--env DB_TYPE=bolt \
|
||||
--constraint=node.role==manager \
|
||||
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
|
||||
--mount=type=bind,src=/data/swirl,dst=/data/swirl \
|
||||
cuigh/swirl
|
||||
```
|
||||
|
||||
* Use **MongoDB** storage engine
|
||||
|
||||
```bash
|
||||
docker service create \
|
||||
--name=swirl \
|
||||
|
152
dao/bolt/bolt.go
Normal file
152
dao/bolt/bolt.go
Normal file
@ -0,0 +1,152 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/auxo/log"
|
||||
)
|
||||
|
||||
type Value []byte
|
||||
|
||||
func (v Value) Unmarshal(i interface{}) error {
|
||||
return json.Unmarshal([]byte(v), i)
|
||||
}
|
||||
|
||||
// Dao implements dao.Interface interface.
|
||||
type Dao struct {
|
||||
logger log.Logger
|
||||
db *bolt.DB
|
||||
}
|
||||
|
||||
// New creates a Dao instance.
|
||||
func New(addr string) (*Dao, error) {
|
||||
if addr == "" {
|
||||
addr = "/data/bolt"
|
||||
}
|
||||
|
||||
db, err := bolt.Open(filepath.Join(addr, "swirl.db"), 0600, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to open bolt database")
|
||||
}
|
||||
|
||||
d := &Dao{
|
||||
logger: log.Get("bolt"),
|
||||
db: db,
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *Dao) Init() {
|
||||
d.db.Update(func(tx *bolt.Tx) error {
|
||||
tx.CreateBucketIfNotExists([]byte("chart"))
|
||||
tx.CreateBucketIfNotExists([]byte("dashboard"))
|
||||
tx.CreateBucketIfNotExists([]byte("event"))
|
||||
tx.CreateBucketIfNotExists([]byte("perm"))
|
||||
tx.CreateBucketIfNotExists([]byte("registry"))
|
||||
tx.CreateBucketIfNotExists([]byte("role"))
|
||||
tx.CreateBucketIfNotExists([]byte("session"))
|
||||
tx.CreateBucketIfNotExists([]byte("setting"))
|
||||
tx.CreateBucketIfNotExists([]byte("stack"))
|
||||
tx.CreateBucketIfNotExists([]byte("template"))
|
||||
tx.CreateBucketIfNotExists([]byte("user"))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) Close() {
|
||||
d.db.Close()
|
||||
}
|
||||
|
||||
func (d *Dao) update(bucket, key string, value interface{}) error {
|
||||
return d.db.Update(func(tx *bolt.Tx) error {
|
||||
buf, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b := tx.Bucket([]byte(bucket))
|
||||
return b.Put([]byte(key), buf)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) delete(bucket, key string) error {
|
||||
return d.db.Update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket))
|
||||
return b.Delete([]byte(key))
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) get(bucket, key string) (val Value, err error) {
|
||||
err = d.db.View(func(tx *bolt.Tx) error {
|
||||
if b := tx.Bucket([]byte(bucket)); b != nil {
|
||||
v := b.Get([]byte(key))
|
||||
if v != nil {
|
||||
val = Value(v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) count(bucket string) (count int, err error) {
|
||||
err = d.db.View(func(tx *bolt.Tx) error {
|
||||
if b := tx.Bucket([]byte(bucket)); b != nil {
|
||||
count = b.Stats().KeyN
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) each(bucket string, fn func(v Value) error) (err error) {
|
||||
return d.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket))
|
||||
return b.ForEach(func(k, v []byte) error {
|
||||
return fn(Value(v))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) slice(bucket string, fn func(v Value) error, keys ...string) (err error) {
|
||||
return d.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket))
|
||||
for _, key := range keys {
|
||||
if data := b.Get([]byte(key)); data != nil {
|
||||
if err = fn(Value(data)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) batch(bucket string, fn func(b *bolt.Bucket) error) (err error) {
|
||||
return d.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket))
|
||||
return fn(b)
|
||||
})
|
||||
}
|
||||
|
||||
func matchAny(s string, list ...string) bool {
|
||||
s = strings.ToLower(s)
|
||||
for _, v := range list {
|
||||
if strings.Contains(strings.ToLower(v), s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// itob returns an 8-byte big endian representation of v.
|
||||
func itob(i uint64) []byte {
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, i)
|
||||
return b
|
||||
}
|
73
dao/bolt/chart.go
Normal file
73
dao/bolt/chart.go
Normal file
@ -0,0 +1,73 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
func (d *Dao) ChartList() (charts []*model.Chart, err error) {
|
||||
err = d.each("chart", func(v Value) error {
|
||||
chart := &model.Chart{}
|
||||
err = v.Unmarshal(chart)
|
||||
if err == nil {
|
||||
charts = append(charts, chart)
|
||||
}
|
||||
return err
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ChartCreate(chart *model.Chart) (err error) {
|
||||
return d.update("chart", chart.Name, chart)
|
||||
}
|
||||
|
||||
func (d *Dao) ChartGet(name string) (chart *model.Chart, err error) {
|
||||
var v Value
|
||||
v, err = d.get("chart", name)
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
chart = &model.Chart{}
|
||||
err = v.Unmarshal(chart)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ChartBatch(names ...string) (charts []*model.Chart, err error) {
|
||||
err = d.slice("chart", func(v Value) error {
|
||||
chart := &model.Chart{}
|
||||
err = v.Unmarshal(chart)
|
||||
if err == nil {
|
||||
charts = append(charts, chart)
|
||||
}
|
||||
return err
|
||||
}, names...)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ChartUpdate(chart *model.Chart) (err error) {
|
||||
return d.update("chart", chart.Name, chart)
|
||||
}
|
||||
|
||||
func (d *Dao) ChartDelete(name string) (err error) {
|
||||
return d.delete("chart", name)
|
||||
}
|
||||
|
||||
func (d *Dao) DashboardGet(name, key string) (dashboard *model.ChartDashboard, err error) {
|
||||
dashboard = &model.ChartDashboard{
|
||||
Name: name,
|
||||
Key: key,
|
||||
}
|
||||
|
||||
var v Value
|
||||
v, err = d.get("dashboard", dashboard.ID())
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
err = v.Unmarshal(dashboard)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) DashboardUpdate(dashboard *model.ChartDashboard) (err error) {
|
||||
return d.update("dashboard", dashboard.ID(), dashboard)
|
||||
}
|
50
dao/bolt/event.go
Normal file
50
dao/bolt/event.go
Normal file
@ -0,0 +1,50 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
func (d *Dao) EventList(args *model.EventListArgs) (events []*model.Event, count int, err error) {
|
||||
err = d.each("event", func(v Value) error {
|
||||
event := &model.Event{}
|
||||
err = v.Unmarshal(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
match := true
|
||||
if args.Name != "" {
|
||||
match = matchAny(args.Name, event.Name)
|
||||
}
|
||||
if match && args.Type != "" {
|
||||
match = string(event.Type) == args.Type
|
||||
}
|
||||
|
||||
if match {
|
||||
events = append(events, event)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
count = len(events)
|
||||
sort.Slice(events, func(i, j int) bool {
|
||||
return events[i].Time.After(events[j].Time)
|
||||
})
|
||||
start, end := misc.Page(count, args.PageIndex, args.PageSize)
|
||||
events = events[start:end]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) EventCreate(event *model.Event) (err error) {
|
||||
// TODO:
|
||||
return d.update("event", event.ID, event)
|
||||
//return nil
|
||||
//d.do(func(db *database) {
|
||||
// err = db.C("event").Insert(event)
|
||||
//})
|
||||
//return
|
||||
}
|
28
dao/bolt/perm.go
Normal file
28
dao/bolt/perm.go
Normal file
@ -0,0 +1,28 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
func (d *Dao) PermGet(resType, resID string) (p *model.Perm, err error) {
|
||||
key := resType + "." + resID
|
||||
var v Value
|
||||
v, err = d.get("perm", key)
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
p = &model.Perm{}
|
||||
err = v.Unmarshal(p)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) PermUpdate(perm *model.Perm) (err error) {
|
||||
key := perm.ResType + "." + perm.ResID
|
||||
return d.update("perm", key, perm)
|
||||
}
|
||||
|
||||
func (d *Dao) PermDelete(resType, resID string) (err error) {
|
||||
key := resType + "." + resID
|
||||
return d.delete("perm", key)
|
||||
}
|
72
dao/bolt/registry.go
Normal file
72
dao/bolt/registry.go
Normal file
@ -0,0 +1,72 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
func (d *Dao) RegistryCreate(registry *model.Registry) (err error) {
|
||||
return d.update("registry", registry.ID, registry)
|
||||
}
|
||||
|
||||
func (d *Dao) RegistryUpdate(registry *model.Registry) (err error) {
|
||||
return d.batch("registry", func(b *bolt.Bucket) error {
|
||||
data := b.Get([]byte(registry.ID))
|
||||
if data == nil {
|
||||
return errors.New("registry not found: " + registry.ID)
|
||||
}
|
||||
|
||||
r := &model.Registry{}
|
||||
err = json.Unmarshal(data, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Name = registry.Name
|
||||
r.URL = registry.URL
|
||||
r.Username = registry.Username
|
||||
if registry.Password != "" {
|
||||
r.Password = registry.Password
|
||||
}
|
||||
r.UpdatedAt = time.Now()
|
||||
data, err = json.Marshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Put([]byte(registry.ID), data)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) RegistryList() (registries []*model.Registry, err error) {
|
||||
err = d.each("registry", func(v Value) error {
|
||||
r := &model.Registry{}
|
||||
err = v.Unmarshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
registries = append(registries, r)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) RegistryGet(id string) (registry *model.Registry, err error) {
|
||||
var v Value
|
||||
v, err = d.get("registry", id)
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
registry = &model.Registry{}
|
||||
err = v.Unmarshal(registry)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) RegistryDelete(id string) (err error) {
|
||||
return d.delete("registry", id)
|
||||
}
|
68
dao/bolt/role.go
Normal file
68
dao/bolt/role.go
Normal file
@ -0,0 +1,68 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
func (d *Dao) RoleList() (roles []*model.Role, err error) {
|
||||
err = d.each("role", func(v Value) error {
|
||||
role := &model.Role{}
|
||||
err = v.Unmarshal(role)
|
||||
if err == nil {
|
||||
roles = append(roles, role)
|
||||
}
|
||||
return err
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) RoleCreate(role *model.Role) (err error) {
|
||||
return d.update("role", role.ID, role)
|
||||
}
|
||||
|
||||
func (d *Dao) RoleGet(id string) (role *model.Role, err error) {
|
||||
var v Value
|
||||
v, err = d.get("role", id)
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
role = &model.Role{}
|
||||
err = v.Unmarshal(role)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) RoleUpdate(role *model.Role) (err error) {
|
||||
return d.batch("role", func(b *bolt.Bucket) error {
|
||||
data := b.Get([]byte(role.ID))
|
||||
if data == nil {
|
||||
return errors.New("role not found: " + role.ID)
|
||||
}
|
||||
|
||||
r := &model.Role{}
|
||||
err = json.Unmarshal(data, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Name = role.Name
|
||||
r.Description = role.Description
|
||||
r.Perms = role.Perms
|
||||
r.UpdatedAt = time.Now()
|
||||
data, err = json.Marshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Put([]byte(role.ID), data)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) RoleDelete(id string) (err error) {
|
||||
return d.delete("role", id)
|
||||
}
|
23
dao/bolt/setting.go
Normal file
23
dao/bolt/setting.go
Normal file
@ -0,0 +1,23 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
const settingID = "0"
|
||||
|
||||
func (d *Dao) SettingGet() (setting *model.Setting, err error) {
|
||||
var v Value
|
||||
v, err = d.get("setting", settingID)
|
||||
if err == nil {
|
||||
setting = &model.Setting{}
|
||||
if v != nil {
|
||||
err = v.Unmarshal(setting)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) SettingUpdate(setting *model.Setting) (err error) {
|
||||
return d.update("setting", settingID, setting)
|
||||
}
|
141
dao/bolt/stack.go
Normal file
141
dao/bolt/stack.go
Normal file
@ -0,0 +1,141 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
//func (d *Dao) ArchiveList(args *model.ArchiveListArgs) (archives []*model.Archive, count int, err error) {
|
||||
// d.do(func(db *database) {
|
||||
// var query bson.M
|
||||
// if args.Name != "" {
|
||||
// query = bson.M{"name": args.Name}
|
||||
// }
|
||||
// q := db.C("archive").Find(query)
|
||||
//
|
||||
// count, err = q.Count()
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// archives = []*model.Archive{}
|
||||
// err = q.Skip(args.PageSize * (args.PageIndex - 1)).Limit(args.PageSize).All(&archives)
|
||||
// })
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (d *Dao) ArchiveCreate(archive *model.Archive) (err error) {
|
||||
// archive.ID = misc.NewID()
|
||||
// archive.CreatedAt = time.Now()
|
||||
// archive.UpdatedAt = archive.CreatedAt
|
||||
//
|
||||
// d.do(func(db *database) {
|
||||
// err = db.C("archive").Insert(archive)
|
||||
// })
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (d *Dao) ArchiveGet(id string) (archive *model.Archive, err error) {
|
||||
// d.do(func(db *database) {
|
||||
// archive = &model.Archive{}
|
||||
// err = db.C("archive").FindId(id).One(archive)
|
||||
// if err == mgo.ErrNotFound {
|
||||
// archive, err = nil, nil
|
||||
// } else if err != nil {
|
||||
// archive = nil
|
||||
// }
|
||||
// })
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (d *Dao) ArchiveUpdate(archive *model.Archive) (err error) {
|
||||
// d.do(func(db *database) {
|
||||
// update := bson.M{
|
||||
// "$set": bson.M{
|
||||
// "name": archive.Name,
|
||||
// "content": archive.Content,
|
||||
// "updated_by": archive.UpdatedBy,
|
||||
// "updated_at": time.Now(),
|
||||
// },
|
||||
// }
|
||||
// err = db.C("archive").UpdateId(archive.ID, update)
|
||||
// })
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (d *Dao) ArchiveDelete(id string) (err error) {
|
||||
// d.do(func(db *database) {
|
||||
// err = db.C("archive").RemoveId(id)
|
||||
// })
|
||||
// return
|
||||
//}
|
||||
|
||||
//===============================
|
||||
|
||||
func (d *Dao) StackList() (stacks []*model.Stack, err error) {
|
||||
err = d.each("stack", func(v Value) error {
|
||||
stack := &model.Stack{}
|
||||
err = v.Unmarshal(stack)
|
||||
if err == nil {
|
||||
stacks = append(stacks, stack)
|
||||
}
|
||||
return err
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) StackCreate(stack *model.Stack) (err error) {
|
||||
stack.CreatedAt = time.Now()
|
||||
stack.UpdatedAt = stack.CreatedAt
|
||||
return d.update("stack", stack.Name, stack)
|
||||
}
|
||||
|
||||
func (d *Dao) StackGet(name string) (stack *model.Stack, err error) {
|
||||
var v Value
|
||||
v, err = d.get("stack", name)
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
stack = &model.Stack{}
|
||||
err = v.Unmarshal(stack)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) StackUpdate(stack *model.Stack) (err error) {
|
||||
return d.batch("stack", func(b *bolt.Bucket) error {
|
||||
data := b.Get([]byte(stack.Name))
|
||||
if data == nil {
|
||||
return errors.New("stack not found: " + stack.Name)
|
||||
}
|
||||
|
||||
s := &model.Stack{}
|
||||
err = json.Unmarshal(data, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Content = stack.Content
|
||||
s.UpdatedBy = stack.UpdatedBy
|
||||
s.UpdatedAt = time.Now()
|
||||
data, err = json.Marshal(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Put([]byte(stack.Name), data)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) StackDelete(name string) (err error) {
|
||||
return d.delete("stack", name)
|
||||
}
|
||||
|
||||
// StackMigrate migrates stacks from old archive collection.
|
||||
func (d *Dao) StackMigrate() {
|
||||
// bolt storage engine was implemented at version 0.7.8, so migration is not required.
|
||||
}
|
80
dao/bolt/template.go
Normal file
80
dao/bolt/template.go
Normal file
@ -0,0 +1,80 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
func (d *Dao) TemplateList(args *model.TemplateListArgs) (tpls []*model.Template, count int, err error) {
|
||||
err = d.each("template", func(v Value) error {
|
||||
t := &model.Template{}
|
||||
err = v.Unmarshal(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if matchAny(args.Name, t.Name) {
|
||||
tpls = append(tpls, t)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
count = len(tpls)
|
||||
start, end := misc.Page(count, args.PageIndex, args.PageSize)
|
||||
tpls = tpls[start:end]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) TemplateCreate(tpl *model.Template) (err error) {
|
||||
tpl.CreatedAt = time.Now()
|
||||
tpl.UpdatedAt = tpl.CreatedAt
|
||||
return d.update("template", tpl.ID, tpl)
|
||||
}
|
||||
|
||||
func (d *Dao) TemplateGet(id string) (tpl *model.Template, err error) {
|
||||
var v Value
|
||||
v, err = d.get("template", id)
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
tpl = &model.Template{}
|
||||
err = v.Unmarshal(tpl)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) TemplateUpdate(tpl *model.Template) (err error) {
|
||||
return d.batch("template", func(b *bolt.Bucket) error {
|
||||
data := b.Get([]byte(tpl.ID))
|
||||
if data == nil {
|
||||
return errors.New("template not found: " + tpl.ID)
|
||||
}
|
||||
|
||||
t := &model.Template{}
|
||||
err = json.Unmarshal(data, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Name = tpl.Name
|
||||
t.Content = tpl.Content
|
||||
t.UpdatedBy = tpl.UpdatedBy
|
||||
t.UpdatedAt = time.Now()
|
||||
data, err = json.Marshal(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Put([]byte(tpl.ID), data)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) TemplateDelete(id string) (err error) {
|
||||
return d.delete("template", id)
|
||||
}
|
173
dao/bolt/user.go
Normal file
173
dao/bolt/user.go
Normal file
@ -0,0 +1,173 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
func (d *Dao) UserCount() (count int, err error) {
|
||||
return d.count("user")
|
||||
}
|
||||
|
||||
func (d *Dao) UserCreate(user *model.User) (err error) {
|
||||
return d.update("user", user.ID, user)
|
||||
}
|
||||
|
||||
func (d *Dao) UserUpdate(user *model.User) (err error) {
|
||||
return d.userUpdate(user.ID, func(u *model.User) {
|
||||
u.Name = user.Name
|
||||
u.Email = user.Email
|
||||
u.Admin = user.Admin
|
||||
u.Type = user.Type
|
||||
u.Roles = user.Roles
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) UserBlock(id string, blocked bool) (err error) {
|
||||
return d.userUpdate(id, func(u *model.User) {
|
||||
if blocked {
|
||||
u.Status = model.UserStatusBlocked
|
||||
} else {
|
||||
u.Status = model.UserStatusActive
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) UserDelete(id string) (err error) {
|
||||
return d.delete("user", id)
|
||||
}
|
||||
|
||||
func (d *Dao) UserList(args *model.UserListArgs) (users []*model.User, count int, err error) {
|
||||
err = d.each("user", func(v Value) error {
|
||||
user := &model.User{}
|
||||
err = v.Unmarshal(user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
match := true
|
||||
if args.Query != "" {
|
||||
match = matchAny(args.Query, user.LoginName, user.Name, user.Email)
|
||||
}
|
||||
if match {
|
||||
switch args.Filter {
|
||||
case "admins":
|
||||
match = user.Admin
|
||||
case "active":
|
||||
match = user.Status == model.UserStatusActive
|
||||
case "blocked":
|
||||
match = user.Status == model.UserStatusBlocked
|
||||
}
|
||||
}
|
||||
|
||||
if match {
|
||||
users = append(users, user)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
count = len(users)
|
||||
start, end := misc.Page(count, args.PageIndex, args.PageSize)
|
||||
users = users[start:end]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) UserGetByID(id string) (user *model.User, err error) {
|
||||
var v Value
|
||||
v, err = d.get("user", id)
|
||||
if err == nil {
|
||||
if v != nil {
|
||||
user = &model.User{}
|
||||
err = v.Unmarshal(user)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) UserGetByName(loginName string) (user *model.User, err error) {
|
||||
err = d.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte("user"))
|
||||
c := b.Cursor()
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
u := &model.User{}
|
||||
err = json.Unmarshal(v, u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if u.LoginName == loginName {
|
||||
user = u
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ProfileUpdateInfo(user *model.User) (err error) {
|
||||
return d.userUpdate(user.ID, func(u *model.User) {
|
||||
u.Name = user.Name
|
||||
u.Email = user.Email
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) ProfileUpdatePassword(id, pwd, salt string) (err error) {
|
||||
return d.userUpdate(id, func(u *model.User) {
|
||||
u.Password = pwd
|
||||
u.Salt = salt
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) userUpdate(id string, decorator func(u *model.User)) (err error) {
|
||||
return d.batch("user", func(b *bolt.Bucket) error {
|
||||
data := b.Get([]byte(id))
|
||||
if data == nil {
|
||||
return errors.New("user not found: " + id)
|
||||
}
|
||||
|
||||
u := &model.User{}
|
||||
err = json.Unmarshal(data, u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
decorator(u)
|
||||
u.UpdatedAt = time.Now()
|
||||
data, err = json.Marshal(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Put([]byte(id), data)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Dao) SessionGet(token string) (session *model.Session, err error) {
|
||||
err = d.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte("session"))
|
||||
c := b.Cursor()
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
s := &model.Session{}
|
||||
err = json.Unmarshal(v, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s.Token == token {
|
||||
session = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) SessionUpdate(session *model.Session) (err error) {
|
||||
return d.update("session", session.UserID, session)
|
||||
}
|
23
dao/dao.go
23
dao/dao.go
@ -3,6 +3,7 @@ package dao
|
||||
import (
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/auxo/util/lazy"
|
||||
"github.com/cuigh/swirl/dao/bolt"
|
||||
"github.com/cuigh/swirl/dao/mongo"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
@ -14,6 +15,9 @@ var (
|
||||
|
||||
// Interface is the interface that wraps all dao methods.
|
||||
type Interface interface {
|
||||
Init()
|
||||
Close()
|
||||
|
||||
RoleGet(id string) (*model.Role, error)
|
||||
RoleList() (roles []*model.Role, err error)
|
||||
RoleCreate(role *model.Role) error
|
||||
@ -41,18 +45,12 @@ type Interface interface {
|
||||
RegistryList() (registries []*model.Registry, err error)
|
||||
RegistryDelete(id string) error
|
||||
|
||||
ArchiveList(args *model.ArchiveListArgs) (archives []*model.Archive, count int, err error)
|
||||
ArchiveGet(id string) (*model.Archive, error)
|
||||
ArchiveCreate(archive *model.Archive) error
|
||||
ArchiveUpdate(archive *model.Archive) error
|
||||
ArchiveDelete(id string) error
|
||||
|
||||
StackList() (stacks []*model.Stack, err error)
|
||||
StackGet(name string) (*model.Stack, error)
|
||||
StackCreate(stack *model.Stack) error
|
||||
StackUpdate(stack *model.Stack) error
|
||||
StackDelete(name string) error
|
||||
// StackMigrate migrates stacks from old archive collection. This method will removed after v0.8.
|
||||
// StackMigrate migrates stacks from old archive collection. This method will be removed after v0.8.
|
||||
StackMigrate()
|
||||
|
||||
TemplateList(args *model.TemplateListArgs) (tpls []*model.Template, count int, err error)
|
||||
@ -92,11 +90,18 @@ func Get() (Interface, error) {
|
||||
}
|
||||
|
||||
func create() (d interface{}, err error) {
|
||||
var i Interface
|
||||
switch misc.Options.DBType {
|
||||
case "", "mongo":
|
||||
return mongo.New(misc.Options.DBAddress)
|
||||
i, err = mongo.New(misc.Options.DBAddress)
|
||||
case "bolt":
|
||||
i, err = bolt.New(misc.Options.DBAddress)
|
||||
default:
|
||||
err = errors.New("Unknown database type: " + misc.Options.DBType)
|
||||
}
|
||||
return
|
||||
|
||||
if err == nil {
|
||||
i.Init()
|
||||
}
|
||||
return i, err
|
||||
}
|
||||
|
@ -72,11 +72,10 @@ func New(addr string) (*Dao, error) {
|
||||
session: s,
|
||||
logger: log.Get("mongo"),
|
||||
}
|
||||
d.createIndexes()
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *Dao) createIndexes() {
|
||||
func (d *Dao) Init() {
|
||||
db := d.db()
|
||||
defer db.Close()
|
||||
|
||||
@ -91,6 +90,10 @@ func (d *Dao) createIndexes() {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dao) Close() {
|
||||
d.session.Close()
|
||||
}
|
||||
|
||||
func (d *Dao) db() *database {
|
||||
return &database{
|
||||
db: d.session.Copy().DB(""),
|
||||
|
@ -5,79 +5,11 @@ import (
|
||||
|
||||
"github.com/cuigh/auxo/app"
|
||||
"github.com/cuigh/auxo/log"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
"github.com/globalsign/mgo"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
func (d *Dao) ArchiveList(args *model.ArchiveListArgs) (archives []*model.Archive, count int, err error) {
|
||||
d.do(func(db *database) {
|
||||
var query bson.M
|
||||
if args.Name != "" {
|
||||
query = bson.M{"name": args.Name}
|
||||
}
|
||||
q := db.C("archive").Find(query)
|
||||
|
||||
count, err = q.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
archives = []*model.Archive{}
|
||||
err = q.Skip(args.PageSize * (args.PageIndex - 1)).Limit(args.PageSize).All(&archives)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ArchiveCreate(archive *model.Archive) (err error) {
|
||||
archive.ID = misc.NewID()
|
||||
archive.CreatedAt = time.Now()
|
||||
archive.UpdatedAt = archive.CreatedAt
|
||||
|
||||
d.do(func(db *database) {
|
||||
err = db.C("archive").Insert(archive)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ArchiveGet(id string) (archive *model.Archive, err error) {
|
||||
d.do(func(db *database) {
|
||||
archive = &model.Archive{}
|
||||
err = db.C("archive").FindId(id).One(archive)
|
||||
if err == mgo.ErrNotFound {
|
||||
archive, err = nil, nil
|
||||
} else if err != nil {
|
||||
archive = nil
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ArchiveUpdate(archive *model.Archive) (err error) {
|
||||
d.do(func(db *database) {
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"name": archive.Name,
|
||||
"content": archive.Content,
|
||||
"updated_by": archive.UpdatedBy,
|
||||
"updated_at": time.Now(),
|
||||
},
|
||||
}
|
||||
err = db.C("archive").UpdateId(archive.ID, update)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) ArchiveDelete(id string) (err error) {
|
||||
d.do(func(db *database) {
|
||||
err = db.C("archive").RemoveId(id)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
//===============================
|
||||
|
||||
func (d *Dao) StackList() (stacks []*model.Stack, err error) {
|
||||
d.do(func(db *database) {
|
||||
stacks = []*model.Stack{}
|
||||
|
9
main.go
9
main.go
@ -33,19 +33,20 @@ func main() {
|
||||
app.Action = func(ctx *app.Context) {
|
||||
err := config.UnmarshalOption("swirl", &misc.Options)
|
||||
if err != nil {
|
||||
log.Get(app.Name).Error("Load options failed: ", err)
|
||||
log.Get(app.Name).Error("Failed to load options: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
setting, err := biz.Setting.Get()
|
||||
if err != nil {
|
||||
log.Get(app.Name).Error("Load setting failed: ", err)
|
||||
log.Get(app.Name).Error("Failed to load settings: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
biz.Stack.Migrate()
|
||||
|
||||
scaler.Start()
|
||||
if setting.Metrics.Prometheus != "" {
|
||||
scaler.Start()
|
||||
}
|
||||
app.Run(server(setting))
|
||||
}
|
||||
app.Flags.Register(flag.All)
|
||||
|
Loading…
Reference in New Issue
Block a user