Add ‘bolt’ storage engine

This commit is contained in:
cuigh 2018-04-27 21:17:00 +08:00
parent a7a4be4d71
commit 4ad92f6c73
17 changed files with 933 additions and 87 deletions

14
Gopkg.lock generated
View File

@ -19,6 +19,13 @@
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f" revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
version = "v0.4.7" 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]] [[projects]]
branch = "master" branch = "master"
name = "github.com/cuigh/auxo" name = "github.com/cuigh/auxo"
@ -208,7 +215,10 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["windows"] packages = [
"unix",
"windows"
]
revision = "2f57af4873d00d535c5c9028850aa2152e6a5566" revision = "2f57af4873d00d535c5c9028850aa2152e6a5566"
[[projects]] [[projects]]
@ -226,6 +236,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "dea823c7646b8b71101e0443b1c0c36a723989261f733ad4cb44c6e9b0d3942d" inputs-digest = "fe9c254e0c7e739370b6380ed53816426b8245a1610db2cfc612aec63aa01701"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -40,3 +40,8 @@ required = ["github.com/docker/distribution"]
[[constraint]] [[constraint]]
name = "github.com/docker/distribution" 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"

View File

@ -75,7 +75,7 @@ Only these options can be set by environment variables for now.
| Name | Value | | Name | Value |
| --------------- | -----------------------------| | --------------- | -----------------------------|
| DB_TYPE | mongo | | DB_TYPE | mongo,bolt |
| DB_ADDRESS | localhost:27017/swirl | | DB_ADDRESS | localhost:27017/swirl |
| DOCKER_ENDPOINT | tcp://docker-proxy:2375 | | DOCKER_ENDPOINT | tcp://docker-proxy:2375 |
| AUTH_TIMEOUT | 4h | | AUTH_TIMEOUT | 4h |
@ -86,6 +86,8 @@ Docker support mounting configuration file through swarm from v17.06, so you can
## Deployment ## 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 ### Stand alone
Just copy the swirl binary and config/assets/views directories to the host, and run it. 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 ### 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 ```bash
docker run -d -p 8001:8001 \ docker run -d -p 8001:8001 \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \ --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 ### 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 ```bash
docker service create \ docker service create \
--name=swirl \ --name=swirl \

152
dao/bolt/bolt.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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)
}

View File

@ -3,6 +3,7 @@ package dao
import ( import (
"github.com/cuigh/auxo/errors" "github.com/cuigh/auxo/errors"
"github.com/cuigh/auxo/util/lazy" "github.com/cuigh/auxo/util/lazy"
"github.com/cuigh/swirl/dao/bolt"
"github.com/cuigh/swirl/dao/mongo" "github.com/cuigh/swirl/dao/mongo"
"github.com/cuigh/swirl/misc" "github.com/cuigh/swirl/misc"
"github.com/cuigh/swirl/model" "github.com/cuigh/swirl/model"
@ -14,6 +15,9 @@ var (
// Interface is the interface that wraps all dao methods. // Interface is the interface that wraps all dao methods.
type Interface interface { type Interface interface {
Init()
Close()
RoleGet(id string) (*model.Role, error) RoleGet(id string) (*model.Role, error)
RoleList() (roles []*model.Role, err error) RoleList() (roles []*model.Role, err error)
RoleCreate(role *model.Role) error RoleCreate(role *model.Role) error
@ -41,18 +45,12 @@ type Interface interface {
RegistryList() (registries []*model.Registry, err error) RegistryList() (registries []*model.Registry, err error)
RegistryDelete(id string) 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) StackList() (stacks []*model.Stack, err error)
StackGet(name string) (*model.Stack, error) StackGet(name string) (*model.Stack, error)
StackCreate(stack *model.Stack) error StackCreate(stack *model.Stack) error
StackUpdate(stack *model.Stack) error StackUpdate(stack *model.Stack) error
StackDelete(name string) 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() StackMigrate()
TemplateList(args *model.TemplateListArgs) (tpls []*model.Template, count int, err error) 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) { func create() (d interface{}, err error) {
var i Interface
switch misc.Options.DBType { switch misc.Options.DBType {
case "", "mongo": 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: default:
err = errors.New("Unknown database type: " + misc.Options.DBType) err = errors.New("Unknown database type: " + misc.Options.DBType)
} }
return
if err == nil {
i.Init()
}
return i, err
} }

View File

@ -72,11 +72,10 @@ func New(addr string) (*Dao, error) {
session: s, session: s,
logger: log.Get("mongo"), logger: log.Get("mongo"),
} }
d.createIndexes()
return d, nil return d, nil
} }
func (d *Dao) createIndexes() { func (d *Dao) Init() {
db := d.db() db := d.db()
defer db.Close() defer db.Close()
@ -91,6 +90,10 @@ func (d *Dao) createIndexes() {
} }
} }
func (d *Dao) Close() {
d.session.Close()
}
func (d *Dao) db() *database { func (d *Dao) db() *database {
return &database{ return &database{
db: d.session.Copy().DB(""), db: d.session.Copy().DB(""),

View File

@ -5,79 +5,11 @@ import (
"github.com/cuigh/auxo/app" "github.com/cuigh/auxo/app"
"github.com/cuigh/auxo/log" "github.com/cuigh/auxo/log"
"github.com/cuigh/swirl/misc"
"github.com/cuigh/swirl/model" "github.com/cuigh/swirl/model"
"github.com/globalsign/mgo" "github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson" "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) { func (d *Dao) StackList() (stacks []*model.Stack, err error) {
d.do(func(db *database) { d.do(func(db *database) {
stacks = []*model.Stack{} stacks = []*model.Stack{}

View File

@ -33,19 +33,20 @@ func main() {
app.Action = func(ctx *app.Context) { app.Action = func(ctx *app.Context) {
err := config.UnmarshalOption("swirl", &misc.Options) err := config.UnmarshalOption("swirl", &misc.Options)
if err != nil { 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) os.Exit(1)
} }
setting, err := biz.Setting.Get() setting, err := biz.Setting.Get()
if err != nil { 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) os.Exit(1)
} }
biz.Stack.Migrate() biz.Stack.Migrate()
if setting.Metrics.Prometheus != "" {
scaler.Start() scaler.Start()
}
app.Run(server(setting)) app.Run(server(setting))
} }
app.Flags.Register(flag.All) app.Flags.Register(flag.All)