mirror of
https://github.com/bingohuang/docker-labs.git
synced 2025-07-15 02:37:27 +08:00
Refactor sessions and add locking to avoid concurrent requests to create
more instances
This commit is contained in:
parent
d19e8a0cd3
commit
a56af3dc22
4
api.go
4
api.go
@ -18,7 +18,7 @@ func main() {
|
|||||||
mux.Get("/", http.HandlerFunc(handlers.NewSession))
|
mux.Get("/", http.HandlerFunc(handlers.NewSession))
|
||||||
mux.Get("/sessions/:sessionId", http.HandlerFunc(handlers.GetSession))
|
mux.Get("/sessions/:sessionId", http.HandlerFunc(handlers.GetSession))
|
||||||
mux.Post("/sessions/:sessionId/instances", http.HandlerFunc(handlers.NewInstance))
|
mux.Post("/sessions/:sessionId/instances", http.HandlerFunc(handlers.NewInstance))
|
||||||
mux.Delete("/sessions/:sessionId/instances/:instanceId", http.HandlerFunc(handlers.DeleteInstance))
|
mux.Delete("/sessions/:sessionId/instances/:instanceName", http.HandlerFunc(handlers.DeleteInstance))
|
||||||
|
|
||||||
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
http.ServeFile(w, r, "./www/index.html")
|
http.ServeFile(w, r, "./www/index.html")
|
||||||
@ -26,7 +26,7 @@ func main() {
|
|||||||
mux.Get("/p/:sessionId", h)
|
mux.Get("/p/:sessionId", h)
|
||||||
mux.Get("/assets/*", http.FileServer(http.Dir("./www")))
|
mux.Get("/assets/*", http.FileServer(http.Dir("./www")))
|
||||||
|
|
||||||
mux.Get("/sessions/:sessionId/instances/:instanceId/attach", websocket.Handler(handlers.Exec))
|
mux.Get("/sessions/:sessionId/instances/:instanceName/attach", websocket.Handler(handlers.Exec))
|
||||||
|
|
||||||
n := negroni.Classic()
|
n := negroni.Classic()
|
||||||
n.UseHandler(mux)
|
n.UseHandler(mux)
|
||||||
|
@ -9,10 +9,10 @@ import (
|
|||||||
|
|
||||||
func DeleteInstance(rw http.ResponseWriter, req *http.Request) {
|
func DeleteInstance(rw http.ResponseWriter, req *http.Request) {
|
||||||
sessionId := bone.GetValue(req, "sessionId")
|
sessionId := bone.GetValue(req, "sessionId")
|
||||||
instanceId := bone.GetValue(req, "instanceId")
|
instanceName := bone.GetValue(req, "instanceName")
|
||||||
|
|
||||||
s := services.GetSession(sessionId)
|
s := services.GetSession(sessionId)
|
||||||
i := services.GetInstance(s, instanceId)
|
i := services.GetInstance(s, instanceName)
|
||||||
err := services.DeleteInstance(s, i)
|
err := services.DeleteInstance(s, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rw.WriteHeader(http.StatusInternalServerError)
|
rw.WriteHeader(http.StatusInternalServerError)
|
||||||
|
@ -15,12 +15,12 @@ import (
|
|||||||
// Echo the data received on the WebSocket.
|
// Echo the data received on the WebSocket.
|
||||||
func Exec(ws *websocket.Conn) {
|
func Exec(ws *websocket.Conn) {
|
||||||
sessionId := bone.GetValue(ws.Request(), "sessionId")
|
sessionId := bone.GetValue(ws.Request(), "sessionId")
|
||||||
instanceId := bone.GetValue(ws.Request(), "instanceId")
|
instanceName := bone.GetValue(ws.Request(), "instanceName")
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
session := services.GetSession(sessionId)
|
session := services.GetSession(sessionId)
|
||||||
instance := services.GetInstance(session, instanceId)
|
instance := services.GetInstance(session, instanceName)
|
||||||
|
|
||||||
if instance.Stdout == nil {
|
if instance.Stdout == nil {
|
||||||
id, err := services.CreateExecConnection(instance.Name, ctx)
|
id, err := services.CreateExecConnection(instance.Name, ctx)
|
||||||
|
@ -14,12 +14,14 @@ func NewInstance(rw http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
s := services.GetSession(sessionId)
|
s := services.GetSession(sessionId)
|
||||||
|
|
||||||
|
s.Lock()
|
||||||
if len(s.Instances) >= 5 {
|
if len(s.Instances) >= 5 {
|
||||||
rw.WriteHeader(http.StatusConflict)
|
rw.WriteHeader(http.StatusConflict)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i, err := services.NewInstance(s)
|
i, err := services.NewInstance(s)
|
||||||
|
s.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
//TODO: Set a status error
|
//TODO: Set a status error
|
||||||
|
@ -7,13 +7,10 @@ import (
|
|||||||
"github.com/franela/play-with-docker/types"
|
"github.com/franela/play-with-docker/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var instances map[string]map[string]*types.Instance
|
|
||||||
|
|
||||||
var dindImage string
|
var dindImage string
|
||||||
var defaultDindImageName string
|
var defaultDindImageName string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
instances = make(map[string]map[string]*types.Instance)
|
|
||||||
dindImage = getDindImageName()
|
dindImage = getDindImageName()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,21 +34,20 @@ func NewInstance(session *types.Session) (*types.Instance, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if instances[session.Id] == nil {
|
if session.Instances == nil {
|
||||||
instances[session.Id] = make(map[string]*types.Instance)
|
session.Instances = make(map[string]*types.Instance)
|
||||||
}
|
}
|
||||||
instances[session.Id][instance.Name] = instance
|
session.Instances[instance.Name] = instance
|
||||||
|
|
||||||
return instance, nil
|
return instance, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInstance(session *types.Session, instanceId string) *types.Instance {
|
func GetInstance(session *types.Session, name string) *types.Instance {
|
||||||
//TODO: Use redis
|
//TODO: Use redis
|
||||||
i := instances[session.Id][instanceId]
|
return session.Instances[name]
|
||||||
return i
|
|
||||||
}
|
}
|
||||||
func DeleteInstance(session *types.Session, instance *types.Instance) error {
|
func DeleteInstance(session *types.Session, instance *types.Instance) error {
|
||||||
//TODO: Use redis
|
//TODO: Use redis
|
||||||
delete(instances[session.Id], instance.Name)
|
delete(session.Instances, instance.Name)
|
||||||
return DeleteContainer(instance.Name)
|
return DeleteContainer(instance.Name)
|
||||||
}
|
}
|
||||||
|
@ -49,11 +49,5 @@ func NewSession() (*types.Session, error) {
|
|||||||
|
|
||||||
func GetSession(sessionId string) *types.Session {
|
func GetSession(sessionId string) *types.Session {
|
||||||
//TODO: Use redis
|
//TODO: Use redis
|
||||||
s, found := sessions[sessionId]
|
return sessions[sessionId]
|
||||||
if found {
|
|
||||||
s.Instances = instances[sessionId]
|
|
||||||
return s
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/franela/play-with-docker/cookoo"
|
"github.com/franela/play-with-docker/cookoo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
|
sync.Mutex
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Instances map[string]*Instance `json:"instances"`
|
Instances map[string]*Instance `json:"instances"`
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user