Multiple playgrounds support (#215)
* Add Playground struct and basic support for creating it and retrieving it * Add missing functions in pwd mock * Get playground from request domain and validate it exists. If valid set it on the newly created session. * Move playground specific configurations to the playground struct and use it everytime we need that conf. * Don't allow to specify a duration bigger that the allowed in the playground
This commit is contained in:
committed by
GitHub
parent
3dee0d3f0b
commit
3f5b3882dd
12
api.go
12
api.go
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
"github.com/play-with-docker/play-with-docker/config"
|
||||||
"github.com/play-with-docker/play-with-docker/docker"
|
"github.com/play-with-docker/play-with-docker/docker"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
"github.com/play-with-docker/play-with-docker/id"
|
"github.com/play-with-docker/play-with-docker/id"
|
||||||
"github.com/play-with-docker/play-with-docker/provisioner"
|
"github.com/play-with-docker/play-with-docker/provisioner"
|
||||||
"github.com/play-with-docker/play-with-docker/pwd"
|
"github.com/play-with-docker/play-with-docker/pwd"
|
||||||
|
"github.com/play-with-docker/play-with-docker/pwd/types"
|
||||||
"github.com/play-with-docker/play-with-docker/scheduler"
|
"github.com/play-with-docker/play-with-docker/scheduler"
|
||||||
"github.com/play-with-docker/play-with-docker/scheduler/task"
|
"github.com/play-with-docker/play-with-docker/scheduler/task"
|
||||||
"github.com/play-with-docker/play-with-docker/storage"
|
"github.com/play-with-docker/play-with-docker/storage"
|
||||||
@@ -41,6 +43,16 @@ func main() {
|
|||||||
|
|
||||||
sch.Start()
|
sch.Start()
|
||||||
|
|
||||||
|
d, err := time.ParseDuration(config.DefaultSessionDuration)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Cannot parse duration %s. Got: %v", config.DefaultSessionDuration, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
playground := types.Playground{Domain: config.PlaygroundDomain, DefaultDinDInstanceImage: config.DefaultDinDImage, AllowWindowsInstances: config.NoWindows, DefaultSessionDuration: d, AvailableDinDInstanceImages: []string{config.DefaultDinDImage}}
|
||||||
|
if _, err := core.PlaygroundNew(playground); err != nil {
|
||||||
|
log.Fatalf("Cannot create default playground. Got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
handlers.Bootstrap(core, e)
|
handlers.Bootstrap(core, e)
|
||||||
handlers.Register(nil)
|
handlers.Register(nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/securecookie"
|
"github.com/gorilla/securecookie"
|
||||||
|
|
||||||
@@ -27,10 +24,9 @@ const (
|
|||||||
var NameFilter = regexp.MustCompile(PWDHostPortGroupRegex)
|
var NameFilter = regexp.MustCompile(PWDHostPortGroupRegex)
|
||||||
var AliasFilter = regexp.MustCompile(AliasPortGroupRegex)
|
var AliasFilter = regexp.MustCompile(AliasPortGroupRegex)
|
||||||
|
|
||||||
var PortNumber, Key, Cert, SessionsFile, PWDContainerName, L2ContainerName, L2Subdomain, PWDCName, HashKey, SSHKeyPath, L2RouterIP, DindVolumeSize, CookieHashKey, CookieBlockKey string
|
var PortNumber, Key, Cert, SessionsFile, PWDContainerName, L2ContainerName, L2Subdomain, HashKey, SSHKeyPath, L2RouterIP, DindVolumeSize, CookieHashKey, CookieBlockKey, DefaultDinDImage, DefaultSessionDuration string
|
||||||
var UseLetsEncrypt, ExternalDindVolume, NoWindows bool
|
var UseLetsEncrypt, ExternalDindVolume, NoWindows bool
|
||||||
var LetsEncryptCertsDir string
|
var LetsEncryptCertsDir string
|
||||||
var LetsEncryptDomains stringslice
|
|
||||||
var MaxLoadAvg float64
|
var MaxLoadAvg float64
|
||||||
var ForceTLS bool
|
var ForceTLS bool
|
||||||
var Providers map[string]*oauth2.Config
|
var Providers map[string]*oauth2.Config
|
||||||
@@ -40,18 +36,9 @@ var GithubClientID, GithubClientSecret string
|
|||||||
var FacebookClientID, FacebookClientSecret string
|
var FacebookClientID, FacebookClientSecret string
|
||||||
var DockerClientID, DockerClientSecret string
|
var DockerClientID, DockerClientSecret string
|
||||||
|
|
||||||
type stringslice []string
|
var PlaygroundDomain string
|
||||||
|
|
||||||
func (i *stringslice) String() string {
|
|
||||||
return fmt.Sprintf("%s", *i)
|
|
||||||
}
|
|
||||||
func (i *stringslice) Set(value string) error {
|
|
||||||
*i = append(*i, value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseFlags() {
|
func ParseFlags() {
|
||||||
flag.Var(&LetsEncryptDomains, "letsencrypt-domain", "List of domains to validate with let's encrypt")
|
|
||||||
flag.StringVar(&LetsEncryptCertsDir, "letsencrypt-certs-dir", "/certs", "Path where let's encrypt certs will be stored")
|
flag.StringVar(&LetsEncryptCertsDir, "letsencrypt-certs-dir", "/certs", "Path where let's encrypt certs will be stored")
|
||||||
flag.BoolVar(&UseLetsEncrypt, "letsencrypt-enable", false, "Enabled let's encrypt tls certificates")
|
flag.BoolVar(&UseLetsEncrypt, "letsencrypt-enable", false, "Enabled let's encrypt tls certificates")
|
||||||
flag.BoolVar(&ForceTLS, "tls", false, "Use TLS to connect to docker daemons")
|
flag.BoolVar(&ForceTLS, "tls", false, "Use TLS to connect to docker daemons")
|
||||||
@@ -63,7 +50,6 @@ func ParseFlags() {
|
|||||||
flag.StringVar(&L2ContainerName, "l2", "l2", "Container name used to run L2 Router")
|
flag.StringVar(&L2ContainerName, "l2", "l2", "Container name used to run L2 Router")
|
||||||
flag.StringVar(&L2RouterIP, "l2-ip", "", "Host IP address for L2 router ping response")
|
flag.StringVar(&L2RouterIP, "l2-ip", "", "Host IP address for L2 router ping response")
|
||||||
flag.StringVar(&L2Subdomain, "l2-subdomain", "direct", "Subdomain to the L2 Router")
|
flag.StringVar(&L2Subdomain, "l2-subdomain", "direct", "Subdomain to the L2 Router")
|
||||||
flag.StringVar(&PWDCName, "cname", "", "CNAME given to this host")
|
|
||||||
flag.StringVar(&HashKey, "hash_key", "salmonrosado", "Hash key to use for cookies")
|
flag.StringVar(&HashKey, "hash_key", "salmonrosado", "Hash key to use for cookies")
|
||||||
flag.StringVar(&DindVolumeSize, "dind-volume-size", "5G", "Dind volume folder size")
|
flag.StringVar(&DindVolumeSize, "dind-volume-size", "5G", "Dind volume folder size")
|
||||||
flag.BoolVar(&NoWindows, "win-disable", false, "Disable windows instances")
|
flag.BoolVar(&NoWindows, "win-disable", false, "Disable windows instances")
|
||||||
@@ -72,6 +58,8 @@ func ParseFlags() {
|
|||||||
flag.StringVar(&SSHKeyPath, "ssh_key_path", "", "SSH Private Key to use")
|
flag.StringVar(&SSHKeyPath, "ssh_key_path", "", "SSH Private Key to use")
|
||||||
flag.StringVar(&CookieHashKey, "cookie-hash-key", "", "Hash key to use to validate cookies")
|
flag.StringVar(&CookieHashKey, "cookie-hash-key", "", "Hash key to use to validate cookies")
|
||||||
flag.StringVar(&CookieBlockKey, "cookie-block-key", "", "Block key to use to encrypt cookies")
|
flag.StringVar(&CookieBlockKey, "cookie-block-key", "", "Block key to use to encrypt cookies")
|
||||||
|
flag.StringVar(&DefaultDinDImage, "default-dind-image", "franela/dind", "Default DinD image to use if not specified otherwise")
|
||||||
|
flag.StringVar(&DefaultSessionDuration, "default-session-duration", "4h", "Default session duration if not specified otherwise")
|
||||||
|
|
||||||
flag.StringVar(&GithubClientID, "oauth-github-client-id", "", "Github OAuth Client ID")
|
flag.StringVar(&GithubClientID, "oauth-github-client-id", "", "Github OAuth Client ID")
|
||||||
flag.StringVar(&GithubClientSecret, "oauth-github-client-secret", "", "Github OAuth Client Secret")
|
flag.StringVar(&GithubClientSecret, "oauth-github-client-secret", "", "Github OAuth Client Secret")
|
||||||
@@ -82,6 +70,8 @@ func ParseFlags() {
|
|||||||
flag.StringVar(&DockerClientID, "oauth-docker-client-id", "", "Docker OAuth Client ID")
|
flag.StringVar(&DockerClientID, "oauth-docker-client-id", "", "Docker OAuth Client ID")
|
||||||
flag.StringVar(&DockerClientSecret, "oauth-docker-client-secret", "", "Docker OAuth Client Secret")
|
flag.StringVar(&DockerClientSecret, "oauth-docker-client-secret", "", "Docker OAuth Client Secret")
|
||||||
|
|
||||||
|
flag.StringVar(&PlaygroundDomain, "playground-domain", "localhost", "Domain to use for the playground")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
SecureCookie = securecookie.New([]byte(CookieHashKey), []byte(CookieBlockKey))
|
SecureCookie = securecookie.New([]byte(CookieHashKey), []byte(CookieBlockKey))
|
||||||
@@ -126,38 +116,3 @@ func registerOAuthProviders() {
|
|||||||
Providers["docker"] = conf
|
Providers["docker"] = conf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDindImageName() string {
|
|
||||||
dindImage := os.Getenv("DIND_IMAGE")
|
|
||||||
defaultDindImageName := "franela/dind"
|
|
||||||
if len(dindImage) == 0 {
|
|
||||||
dindImage = defaultDindImageName
|
|
||||||
}
|
|
||||||
return dindImage
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSSHImage() string {
|
|
||||||
sshImage := os.Getenv("SSH_IMAGE")
|
|
||||||
defaultSSHImage := "franela/ssh"
|
|
||||||
if len(sshImage) == 0 {
|
|
||||||
return defaultSSHImage
|
|
||||||
}
|
|
||||||
return sshImage
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDuration(reqDur string) time.Duration {
|
|
||||||
var defaultDuration = 4 * time.Hour
|
|
||||||
if reqDur != "" {
|
|
||||||
if dur, err := time.ParseDuration(reqDur); err == nil && dur <= defaultDuration {
|
|
||||||
return dur
|
|
||||||
}
|
|
||||||
return defaultDuration
|
|
||||||
}
|
|
||||||
|
|
||||||
envDur := os.Getenv("EXPIRY")
|
|
||||||
if dur, err := time.ParseDuration(envDur); err == nil {
|
|
||||||
return dur
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultDuration
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,16 +14,13 @@ services:
|
|||||||
# use the latest golang image
|
# use the latest golang image
|
||||||
image: golang
|
image: golang
|
||||||
# go to the right place and starts the app
|
# go to the right place and starts the app
|
||||||
command: /bin/sh -c 'ssh-keygen -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key >/dev/null; cd /go/src/github.com/play-with-docker/play-with-docker; go run api.go -save /pwd/sessions -name l2'
|
command: /bin/sh -c 'ssh-keygen -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key >/dev/null; cd /go/src/github.com/play-with-docker/play-with-docker; go run api.go -save /pwd/sessions -name l2 -default-dind-image franela/dind:hybrid'
|
||||||
volumes:
|
volumes:
|
||||||
# since this app creates networks and launches containers, we need to talk to docker daemon
|
# since this app creates networks and launches containers, we need to talk to docker daemon
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
# mount the box mounted shared folder to the container
|
# mount the box mounted shared folder to the container
|
||||||
- $GOPATH/src:/go/src
|
- $GOPATH/src:/go/src
|
||||||
- sessions:/pwd
|
- sessions:/pwd
|
||||||
environment:
|
|
||||||
GOOGLE_RECAPTCHA_DISABLED: "true"
|
|
||||||
DIND_IMAGE: "franela/dind:hybrid"
|
|
||||||
l2:
|
l2:
|
||||||
container_name: l2
|
container_name: l2
|
||||||
# use the latest golang image
|
# use the latest golang image
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
|
|
||||||
gh "github.com/gorilla/handlers"
|
gh "github.com/gorilla/handlers"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
"github.com/play-with-docker/play-with-docker/config"
|
||||||
"github.com/play-with-docker/play-with-docker/event"
|
"github.com/play-with-docker/play-with-docker/event"
|
||||||
"github.com/play-with-docker/play-with-docker/pwd"
|
"github.com/play-with-docker/play-with-docker/pwd"
|
||||||
@@ -92,9 +94,21 @@ func Register(extend HandlerExtender) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.UseLetsEncrypt {
|
if config.UseLetsEncrypt {
|
||||||
|
domainCache, err := lru.New(5000)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Could not start domain cache. Got: %v", err)
|
||||||
|
}
|
||||||
certManager := autocert.Manager{
|
certManager := autocert.Manager{
|
||||||
Prompt: autocert.AcceptTOS,
|
Prompt: autocert.AcceptTOS,
|
||||||
HostPolicy: autocert.HostWhitelist(config.LetsEncryptDomains...),
|
HostPolicy: func(ctx context.Context, host string) error {
|
||||||
|
if _, found := domainCache.Get(host); !found {
|
||||||
|
if playground := core.PlaygroundFindByDomain(host); playground == nil {
|
||||||
|
return fmt.Errorf("Playground for domain %s was not found", host)
|
||||||
|
}
|
||||||
|
domainCache.Add(host, true)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
Cache: autocert.DirCache(config.LetsEncryptCertsDir),
|
Cache: autocert.DirCache(config.LetsEncryptCertsDir),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package handlers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetInstanceImages(rw http.ResponseWriter, req *http.Request) {
|
func GetInstanceImages(rw http.ResponseWriter, req *http.Request) {
|
||||||
instanceImages := []string{
|
playground := core.PlaygroundFindByDomain(req.Host)
|
||||||
config.GetDindImageName(),
|
if playground == nil {
|
||||||
"franela/dind:dev",
|
log.Printf("Playground for domain %s was not found!", req.Host)
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
json.NewEncoder(rw).Encode(instanceImages)
|
json.NewEncoder(rw).Encode(playground.AvailableDinDInstanceImages)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Home(w http.ResponseWriter, r *http.Request) {
|
func Home(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -21,7 +21,14 @@ func Home(w http.ResponseWriter, r *http.Request) {
|
|||||||
go core.SessionDeployStack(s)
|
go core.SessionDeployStack(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.NoWindows {
|
playground := core.PlaygroundGet(s.PlaygroundId)
|
||||||
|
if playground == nil {
|
||||||
|
log.Printf("Playground with id %s for session %s was not found!", s.PlaygroundId, s.Id)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !playground.AllowWindowsInstances {
|
||||||
http.ServeFile(w, r, "./www/index-nw.html")
|
http.ServeFile(w, r, "./www/index-nw.html")
|
||||||
} else {
|
} else {
|
||||||
http.ServeFile(w, r, "./www/index.html")
|
http.ServeFile(w, r, "./www/index.html")
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
|
||||||
"github.com/play-with-docker/play-with-docker/provisioner"
|
"github.com/play-with-docker/play-with-docker/provisioner"
|
||||||
"github.com/play-with-docker/play-with-docker/pwd"
|
"github.com/play-with-docker/play-with-docker/pwd"
|
||||||
"github.com/play-with-docker/play-with-docker/pwd/types"
|
"github.com/play-with-docker/play-with-docker/pwd/types"
|
||||||
@@ -23,7 +22,14 @@ func NewInstance(rw http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
s := core.SessionGet(sessionId)
|
s := core.SessionGet(sessionId)
|
||||||
|
|
||||||
if body.Type == "windows" && config.NoWindows {
|
playground := core.PlaygroundGet(s.PlaygroundId)
|
||||||
|
if playground == nil {
|
||||||
|
log.Printf("Playground with id %s for session %s was not found!", s.PlaygroundId, s.Id)
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if body.Type == "windows" && !playground.AllowWindowsInstances {
|
||||||
rw.WriteHeader(http.StatusUnauthorized)
|
rw.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
"github.com/play-with-docker/play-with-docker/config"
|
||||||
"github.com/play-with-docker/play-with-docker/provisioner"
|
"github.com/play-with-docker/play-with-docker/provisioner"
|
||||||
@@ -49,8 +50,32 @@ func NewSession(rw http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
duration := config.GetDuration(reqDur)
|
|
||||||
s, err := core.SessionNew(userId, duration, stack, stackName, imageName)
|
playground := core.PlaygroundFindByDomain(req.Host)
|
||||||
|
if playground == nil {
|
||||||
|
log.Printf("Playground for domain %s was not found!", req.Host)
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var duration time.Duration
|
||||||
|
if reqDur != "" {
|
||||||
|
d, err := time.ParseDuration(reqDur)
|
||||||
|
if err != nil {
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d > playground.DefaultSessionDuration {
|
||||||
|
log.Printf("Specified session duration was %s but maximum allowed by this playground is %d\n", d.String(), playground.DefaultSessionDuration.String())
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
duration = d
|
||||||
|
} else {
|
||||||
|
duration = playground.DefaultSessionDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := core.SessionNew(playground, userId, duration, stack, stackName, imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if provisioner.OutOfCapacity(err) {
|
if provisioner.OutOfCapacity(err) {
|
||||||
http.Redirect(rw, req, "/ooc", http.StatusFound)
|
http.Redirect(rw, req, "/ooc", http.StatusFound)
|
||||||
@@ -62,9 +87,6 @@ func NewSession(rw http.ResponseWriter, req *http.Request) {
|
|||||||
//TODO: Return some error code
|
//TODO: Return some error code
|
||||||
} else {
|
} else {
|
||||||
hostname := req.Host
|
hostname := req.Host
|
||||||
if config.PWDCName != "" {
|
|
||||||
hostname = fmt.Sprintf("%s.%s", config.PWDCName, req.Host)
|
|
||||||
}
|
|
||||||
// If request is not a form, return sessionId in the body
|
// If request is not a form, return sessionId in the body
|
||||||
if req.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
if req.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||||
resp := NewSessionResponse{SessionId: s.Id, Hostname: hostname}
|
resp := NewSessionResponse{SessionId: s.Id, Hostname: hostname}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
|
||||||
"github.com/play-with-docker/play-with-docker/docker"
|
"github.com/play-with-docker/play-with-docker/docker"
|
||||||
"github.com/play-with-docker/play-with-docker/id"
|
"github.com/play-with-docker/play-with-docker/id"
|
||||||
"github.com/play-with-docker/play-with-docker/pwd/types"
|
"github.com/play-with-docker/play-with-docker/pwd/types"
|
||||||
@@ -44,7 +43,11 @@ func checkHostnameExists(sessionId, hostname string, instances []*types.Instance
|
|||||||
|
|
||||||
func (d *DinD) InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) {
|
func (d *DinD) InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) {
|
||||||
if conf.ImageName == "" {
|
if conf.ImageName == "" {
|
||||||
conf.ImageName = config.GetDindImageName()
|
playground, err := d.storage.PlaygroundGet(session.PlaygroundId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conf.ImageName = playground.DefaultDinDInstanceImage
|
||||||
}
|
}
|
||||||
log.Printf("NewInstance - using image: [%s]\n", conf.ImageName)
|
log.Printf("NewInstance - using image: [%s]\n", conf.ImageName)
|
||||||
if conf.Hostname == "" {
|
if conf.Hostname == "" {
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ func TestClientNew(t *testing.T) {
|
|||||||
p := NewPWD(_f, _e, _s, sp, ipf)
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
p.generator = _g
|
p.generator = _g
|
||||||
|
|
||||||
session, err := p.SessionNew("", time.Hour, "", "", "")
|
playground := &types.Playground{Id: "foobar"}
|
||||||
|
|
||||||
|
session, err := p.SessionNew(playground, "", time.Hour, "", "", "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
client := p.ClientNew("foobar", session)
|
client := p.ClientNew("foobar", session)
|
||||||
@@ -81,8 +83,9 @@ func TestClientCount(t *testing.T) {
|
|||||||
|
|
||||||
p := NewPWD(_f, _e, _s, sp, ipf)
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
p.generator = _g
|
p.generator = _g
|
||||||
|
playground := &types.Playground{Id: "foobar"}
|
||||||
|
|
||||||
session, err := p.SessionNew("", time.Hour, "", "", "")
|
session, err := p.SessionNew(playground, "", time.Hour, "", "", "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
p.ClientNew("foobar", session)
|
p.ClientNew("foobar", session)
|
||||||
@@ -122,8 +125,9 @@ func TestClientResizeViewPort(t *testing.T) {
|
|||||||
_e.M.On("Emit", event.INSTANCE_VIEWPORT_RESIZE, "aaaabbbbcccc", []interface{}{uint(80), uint(24)}).Return()
|
_e.M.On("Emit", event.INSTANCE_VIEWPORT_RESIZE, "aaaabbbbcccc", []interface{}{uint(80), uint(24)}).Return()
|
||||||
p := NewPWD(_f, _e, _s, sp, ipf)
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
p.generator = _g
|
p.generator = _g
|
||||||
|
playground := &types.Playground{Id: "foobar"}
|
||||||
|
|
||||||
session, err := p.SessionNew("", time.Hour, "", "", "")
|
session, err := p.SessionNew(playground, "", time.Hour, "", "", "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
client := p.ClientNew("foobar", session)
|
client := p.ClientNew("foobar", session)
|
||||||
_s.On("ClientFindBySessionId", "aaaabbbbcccc").Return([]*types.Client{client}, nil)
|
_s.On("ClientFindBySessionId", "aaaabbbbcccc").Return([]*types.Client{client}, nil)
|
||||||
|
|||||||
@@ -70,7 +70,11 @@ func TestInstanceNew(t *testing.T) {
|
|||||||
p := NewPWD(_f, _e, _s, sp, ipf)
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
p.generator = _g
|
p.generator = _g
|
||||||
|
|
||||||
session, err := p.SessionNew("", time.Hour, "", "", "")
|
playground := &types.Playground{Id: "foobar", DefaultDinDInstanceImage: "franela/dind"}
|
||||||
|
|
||||||
|
_s.On("PlaygroundGet", "foobar").Return(playground, nil)
|
||||||
|
|
||||||
|
session, err := p.SessionNew(playground, "", time.Hour, "", "", "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
expectedInstance := types.Instance{
|
expectedInstance := types.Instance{
|
||||||
@@ -78,7 +82,7 @@ func TestInstanceNew(t *testing.T) {
|
|||||||
Hostname: "node1",
|
Hostname: "node1",
|
||||||
IP: "10.0.0.1",
|
IP: "10.0.0.1",
|
||||||
RoutableIP: "10.0.0.1",
|
RoutableIP: "10.0.0.1",
|
||||||
Image: config.GetDindImageName(),
|
Image: "franela/dind",
|
||||||
SessionId: session.Id,
|
SessionId: session.Id,
|
||||||
SessionHost: session.Host,
|
SessionHost: session.Host,
|
||||||
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
||||||
@@ -138,7 +142,8 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
|
|||||||
p := NewPWD(_f, _e, _s, sp, ipf)
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
p.generator = _g
|
p.generator = _g
|
||||||
|
|
||||||
session, err := p.SessionNew("", time.Hour, "", "", "")
|
playground := &types.Playground{Id: "foobar"}
|
||||||
|
session, err := p.SessionNew(playground, "", time.Hour, "", "", "")
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
@@ -207,7 +212,8 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
|
|||||||
p := NewPWD(_f, _e, _s, sp, ipf)
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
p.generator = _g
|
p.generator = _g
|
||||||
|
|
||||||
session, err := p.SessionNew("", time.Hour, "", "", "")
|
playground := &types.Playground{Id: "foobar"}
|
||||||
|
session, err := p.SessionNew(playground, "", time.Hour, "", "", "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
expectedInstance := types.Instance{
|
expectedInstance := types.Instance{
|
||||||
|
|||||||
22
pwd/mock.go
22
pwd/mock.go
@@ -13,7 +13,7 @@ type Mock struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mock) SessionNew(userId string, duration time.Duration, stack string, stackName, imageName string) (*types.Session, error) {
|
func (m *Mock) SessionNew(playground *types.Playground, userId string, duration time.Duration, stack string, stackName, imageName string) (*types.Session, error) {
|
||||||
args := m.Called(duration, stack, stackName, imageName)
|
args := m.Called(duration, stack, stackName, imageName)
|
||||||
return args.Get(0).(*types.Session), args.Error(1)
|
return args.Get(0).(*types.Session), args.Error(1)
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,27 @@ func (m *Mock) UserLogin(loginRequest *types.LoginRequest, user *types.User) (*t
|
|||||||
args := m.Called(loginRequest, user)
|
args := m.Called(loginRequest, user)
|
||||||
return args.Get(0).(*types.User), args.Error(1)
|
return args.Get(0).(*types.User), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mock) UserGet(id string) (*types.User, error) {
|
func (m *Mock) UserGet(id string) (*types.User, error) {
|
||||||
args := m.Called(id)
|
args := m.Called(id)
|
||||||
return args.Get(0).(*types.User), args.Error(1)
|
return args.Get(0).(*types.User), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Mock) PlaygroundNew(playground types.Playground) (*types.Playground, error) {
|
||||||
|
args := m.Called(playground)
|
||||||
|
return args.Get(0).(*types.Playground), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mock) PlaygroundGet(id string) *types.Playground {
|
||||||
|
args := m.Called(id)
|
||||||
|
return args.Get(0).(*types.Playground)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mock) PlaygroundFindByDomain(domain string) *types.Playground {
|
||||||
|
args := m.Called(domain)
|
||||||
|
return args.Get(0).(*types.Playground)
|
||||||
|
}
|
||||||
|
func (m *Mock) PlaygroundList() ([]*types.Playground, error) {
|
||||||
|
args := m.Called()
|
||||||
|
return args.Get(0).([]*types.Playground), args.Error(1)
|
||||||
|
}
|
||||||
|
|||||||
36
pwd/playground.go
Normal file
36
pwd/playground.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package pwd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/play-with-docker/play-with-docker/pwd/types"
|
||||||
|
"github.com/twinj/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *pwd) PlaygroundNew(playground types.Playground) (*types.Playground, error) {
|
||||||
|
playground.Id = uuid.NewV5(uuid.NameSpaceURL, uuid.Name(playground.Domain)).String()
|
||||||
|
if err := p.storage.PlaygroundPut(&playground); err != nil {
|
||||||
|
log.Printf("Error saving playground %s. Got: %v\n", playground.Id, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &playground, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pwd) PlaygroundGet(id string) *types.Playground {
|
||||||
|
if playground, err := p.storage.PlaygroundGet(id); err != nil {
|
||||||
|
log.Printf("Error retrieving playground %s. Got: %v\n", id, err)
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return playground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pwd) PlaygroundFindByDomain(domain string) *types.Playground {
|
||||||
|
id := uuid.NewV5(uuid.NameSpaceURL, uuid.Name(domain)).String()
|
||||||
|
return p.PlaygroundGet(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pwd) PlaygroundList() ([]*types.Playground, error) {
|
||||||
|
return p.storage.PlaygroundGetAll()
|
||||||
|
}
|
||||||
152
pwd/playground_test.go
Normal file
152
pwd/playground_test.go
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
package pwd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/play-with-docker/play-with-docker/docker"
|
||||||
|
"github.com/play-with-docker/play-with-docker/event"
|
||||||
|
"github.com/play-with-docker/play-with-docker/id"
|
||||||
|
"github.com/play-with-docker/play-with-docker/provisioner"
|
||||||
|
"github.com/play-with-docker/play-with-docker/pwd/types"
|
||||||
|
"github.com/play-with-docker/play-with-docker/storage"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"github.com/twinj/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPlaygroundNew(t *testing.T) {
|
||||||
|
_d := &docker.Mock{}
|
||||||
|
_f := &docker.FactoryMock{}
|
||||||
|
_s := &storage.Mock{}
|
||||||
|
_g := &id.MockGenerator{}
|
||||||
|
_e := &event.Mock{}
|
||||||
|
|
||||||
|
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_g, _f, _s))
|
||||||
|
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||||
|
|
||||||
|
_s.On("PlaygroundPut", mock.AnythingOfType("*types.Playground")).Return(nil)
|
||||||
|
|
||||||
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
|
p.generator = _g
|
||||||
|
|
||||||
|
expectedPlayground := types.Playground{Domain: "localhost", DefaultDinDInstanceImage: "franela/dind", AllowWindowsInstances: false, DefaultSessionDuration: time.Hour * 3, Extras: types.PlaygroundExtras{"foo": "bar"}}
|
||||||
|
playground, e := p.PlaygroundNew(expectedPlayground)
|
||||||
|
assert.Nil(t, e)
|
||||||
|
assert.NotNil(t, playground)
|
||||||
|
|
||||||
|
expectedPlayground.Id = uuid.NewV5(uuid.NameSpaceURL, uuid.Name("localhost")).String()
|
||||||
|
assert.Equal(t, expectedPlayground, *playground)
|
||||||
|
|
||||||
|
_d.AssertExpectations(t)
|
||||||
|
_f.AssertExpectations(t)
|
||||||
|
_s.AssertExpectations(t)
|
||||||
|
_g.AssertExpectations(t)
|
||||||
|
_e.M.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlaygroundGet(t *testing.T) {
|
||||||
|
_d := &docker.Mock{}
|
||||||
|
_f := &docker.FactoryMock{}
|
||||||
|
_s := &storage.Mock{}
|
||||||
|
_g := &id.MockGenerator{}
|
||||||
|
_e := &event.Mock{}
|
||||||
|
|
||||||
|
_s.On("PlaygroundPut", mock.AnythingOfType("*types.Playground")).Return(nil)
|
||||||
|
|
||||||
|
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_g, _f, _s))
|
||||||
|
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||||
|
|
||||||
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
|
p.generator = _g
|
||||||
|
|
||||||
|
expectedPlayground := types.Playground{Domain: "localhost", DefaultDinDInstanceImage: "franela/dind", AllowWindowsInstances: false, DefaultSessionDuration: time.Hour * 3, Extras: types.PlaygroundExtras{"foo": "bar"}}
|
||||||
|
playground, e := p.PlaygroundNew(expectedPlayground)
|
||||||
|
assert.Nil(t, e)
|
||||||
|
assert.NotNil(t, playground)
|
||||||
|
|
||||||
|
_s.On("PlaygroundGet", playground.Id).Return(playground, nil)
|
||||||
|
|
||||||
|
playground2 := p.PlaygroundGet(playground.Id)
|
||||||
|
assert.NotNil(t, playground2)
|
||||||
|
|
||||||
|
assert.Equal(t, *playground, *playground2)
|
||||||
|
|
||||||
|
_d.AssertExpectations(t)
|
||||||
|
_f.AssertExpectations(t)
|
||||||
|
_s.AssertExpectations(t)
|
||||||
|
_g.AssertExpectations(t)
|
||||||
|
_e.M.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlaygroundFindByDomain(t *testing.T) {
|
||||||
|
_d := &docker.Mock{}
|
||||||
|
_f := &docker.FactoryMock{}
|
||||||
|
_s := &storage.Mock{}
|
||||||
|
_g := &id.MockGenerator{}
|
||||||
|
_e := &event.Mock{}
|
||||||
|
|
||||||
|
_s.On("PlaygroundPut", mock.AnythingOfType("*types.Playground")).Return(nil)
|
||||||
|
|
||||||
|
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_g, _f, _s))
|
||||||
|
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||||
|
|
||||||
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
|
p.generator = _g
|
||||||
|
|
||||||
|
expectedPlayground := types.Playground{Domain: "localhost", DefaultDinDInstanceImage: "franela/dind", AllowWindowsInstances: false, DefaultSessionDuration: time.Hour * 3, Extras: types.PlaygroundExtras{"foo": "bar"}}
|
||||||
|
playground, e := p.PlaygroundNew(expectedPlayground)
|
||||||
|
assert.Nil(t, e)
|
||||||
|
assert.NotNil(t, playground)
|
||||||
|
|
||||||
|
_s.On("PlaygroundGet", playground.Id).Return(playground, nil)
|
||||||
|
|
||||||
|
playground2 := p.PlaygroundFindByDomain("localhost")
|
||||||
|
assert.NotNil(t, playground2)
|
||||||
|
|
||||||
|
assert.Equal(t, *playground, *playground2)
|
||||||
|
|
||||||
|
_d.AssertExpectations(t)
|
||||||
|
_f.AssertExpectations(t)
|
||||||
|
_s.AssertExpectations(t)
|
||||||
|
_g.AssertExpectations(t)
|
||||||
|
_e.M.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlaygroundList(t *testing.T) {
|
||||||
|
_d := &docker.Mock{}
|
||||||
|
_f := &docker.FactoryMock{}
|
||||||
|
_s := &storage.Mock{}
|
||||||
|
_g := &id.MockGenerator{}
|
||||||
|
_e := &event.Mock{}
|
||||||
|
|
||||||
|
_s.On("PlaygroundPut", mock.AnythingOfType("*types.Playground")).Return(nil)
|
||||||
|
|
||||||
|
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_g, _f, _s))
|
||||||
|
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||||
|
|
||||||
|
p := NewPWD(_f, _e, _s, sp, ipf)
|
||||||
|
p.generator = _g
|
||||||
|
|
||||||
|
pd := types.Playground{Domain: "localhost1", DefaultDinDInstanceImage: "franela/dind", AllowWindowsInstances: false, DefaultSessionDuration: time.Hour * 3, Extras: types.PlaygroundExtras{"foo": "bar"}}
|
||||||
|
p1, e := p.PlaygroundNew(pd)
|
||||||
|
assert.Nil(t, e)
|
||||||
|
assert.NotNil(t, p1)
|
||||||
|
|
||||||
|
pd = types.Playground{Domain: "localhost2", DefaultDinDInstanceImage: "franela/dind", AllowWindowsInstances: false, DefaultSessionDuration: time.Hour * 3, Extras: types.PlaygroundExtras{"foo": "bar"}}
|
||||||
|
p2, e := p.PlaygroundNew(pd)
|
||||||
|
assert.Nil(t, e)
|
||||||
|
assert.NotNil(t, p2)
|
||||||
|
|
||||||
|
_s.On("PlaygroundGetAll").Return([]*types.Playground{p1, p2}, nil)
|
||||||
|
|
||||||
|
received, err := p.PlaygroundList()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, received)
|
||||||
|
|
||||||
|
_d.AssertExpectations(t)
|
||||||
|
_f.AssertExpectations(t)
|
||||||
|
_s.AssertExpectations(t)
|
||||||
|
_g.AssertExpectations(t)
|
||||||
|
_e.M.AssertExpectations(t)
|
||||||
|
}
|
||||||
@@ -72,7 +72,7 @@ func SessionNotEmpty(e error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PWDApi interface {
|
type PWDApi interface {
|
||||||
SessionNew(userId string, duration time.Duration, stack string, stackName, imageName string) (*types.Session, error)
|
SessionNew(playground *types.Playground, userId string, duration time.Duration, stack string, stackName, imageName string) (*types.Session, error)
|
||||||
SessionClose(session *types.Session) error
|
SessionClose(session *types.Session) error
|
||||||
SessionGetSmallestViewPort(sessionId string) types.ViewPort
|
SessionGetSmallestViewPort(sessionId string) types.ViewPort
|
||||||
SessionDeployStack(session *types.Session) error
|
SessionDeployStack(session *types.Session) error
|
||||||
@@ -98,6 +98,11 @@ type PWDApi interface {
|
|||||||
UserGetLoginRequest(id string) (*types.LoginRequest, error)
|
UserGetLoginRequest(id string) (*types.LoginRequest, error)
|
||||||
UserLogin(loginRequest *types.LoginRequest, user *types.User) (*types.User, error)
|
UserLogin(loginRequest *types.LoginRequest, user *types.User) (*types.User, error)
|
||||||
UserGet(id string) (*types.User, error)
|
UserGet(id string) (*types.User, error)
|
||||||
|
|
||||||
|
PlaygroundNew(playground types.Playground) (*types.Playground, error)
|
||||||
|
PlaygroundGet(id string) *types.Playground
|
||||||
|
PlaygroundFindByDomain(domain string) *types.Playground
|
||||||
|
PlaygroundList() ([]*types.Playground, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPWD(f docker.FactoryApi, e event.EventApi, s storage.StorageApi, sp provisioner.SessionProvisionerApi, ipf provisioner.InstanceProvisionerFactoryApi) *pwd {
|
func NewPWD(f docker.FactoryApi, e event.EventApi, s storage.StorageApi, sp provisioner.SessionProvisionerApi, ipf provisioner.InstanceProvisionerFactoryApi) *pwd {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ type SessionSetupInstanceConf struct {
|
|||||||
Tls bool `json:"tls"`
|
Tls bool `json:"tls"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pwd) SessionNew(userId string, duration time.Duration, stack, stackName, imageName string) (*types.Session, error) {
|
func (p *pwd) SessionNew(playground *types.Playground, userId string, duration time.Duration, stack, stackName, imageName string) (*types.Session, error) {
|
||||||
defer observeAction("SessionNew", time.Now())
|
defer observeAction("SessionNew", time.Now())
|
||||||
|
|
||||||
s := &types.Session{}
|
s := &types.Session{}
|
||||||
@@ -54,6 +54,7 @@ func (p *pwd) SessionNew(userId string, duration time.Duration, stack, stackName
|
|||||||
s.Ready = true
|
s.Ready = true
|
||||||
s.Stack = stack
|
s.Stack = stack
|
||||||
s.UserId = userId
|
s.UserId = userId
|
||||||
|
s.PlaygroundId = playground.Id
|
||||||
|
|
||||||
if s.Stack != "" {
|
if s.Stack != "" {
|
||||||
s.Ready = false
|
s.Ready = false
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/play-with-docker/play-with-docker/event"
|
"github.com/play-with-docker/play-with-docker/event"
|
||||||
"github.com/play-with-docker/play-with-docker/id"
|
"github.com/play-with-docker/play-with-docker/id"
|
||||||
"github.com/play-with-docker/play-with-docker/provisioner"
|
"github.com/play-with-docker/play-with-docker/provisioner"
|
||||||
|
"github.com/play-with-docker/play-with-docker/pwd/types"
|
||||||
"github.com/play-with-docker/play-with-docker/storage"
|
"github.com/play-with-docker/play-with-docker/storage"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
@@ -45,7 +46,8 @@ func TestSessionNew(t *testing.T) {
|
|||||||
|
|
||||||
before := time.Now()
|
before := time.Now()
|
||||||
|
|
||||||
s, e := p.SessionNew("", time.Hour, "", "", "")
|
playground := &types.Playground{Id: "foobar"}
|
||||||
|
s, e := p.SessionNew(playground, "", time.Hour, "", "", "")
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.NotNil(t, s)
|
assert.NotNil(t, s)
|
||||||
|
|
||||||
@@ -56,12 +58,13 @@ func TestSessionNew(t *testing.T) {
|
|||||||
assert.WithinDuration(t, s.ExpiresAt, before.Add(time.Hour), time.Second)
|
assert.WithinDuration(t, s.ExpiresAt, before.Add(time.Hour), time.Second)
|
||||||
assert.True(t, s.Ready)
|
assert.True(t, s.Ready)
|
||||||
|
|
||||||
s, _ = p.SessionNew("", time.Hour, "stackPath", "stackName", "imageName")
|
s, _ = p.SessionNew(playground, "", time.Hour, "stackPath", "stackName", "imageName")
|
||||||
|
|
||||||
assert.Equal(t, "stackPath", s.Stack)
|
assert.Equal(t, "stackPath", s.Stack)
|
||||||
assert.Equal(t, "stackName", s.StackName)
|
assert.Equal(t, "stackName", s.StackName)
|
||||||
assert.Equal(t, "imageName", s.ImageName)
|
assert.Equal(t, "imageName", s.ImageName)
|
||||||
assert.Equal(t, "localhost", s.Host)
|
assert.Equal(t, "localhost", s.Host)
|
||||||
|
assert.Equal(t, playground.Id, s.PlaygroundId)
|
||||||
assert.False(t, s.Ready)
|
assert.False(t, s.Ready)
|
||||||
|
|
||||||
_d.AssertExpectations(t)
|
_d.AssertExpectations(t)
|
||||||
|
|||||||
83
pwd/types/playground.go
Normal file
83
pwd/types/playground.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PlaygroundExtras map[string]interface{}
|
||||||
|
|
||||||
|
func (e PlaygroundExtras) Get(name string) (interface{}, bool) {
|
||||||
|
v, f := e[name]
|
||||||
|
return v, f
|
||||||
|
}
|
||||||
|
func (e PlaygroundExtras) GetInt(name string) (int, bool) {
|
||||||
|
v, f := e[name]
|
||||||
|
if f {
|
||||||
|
if r, ok := v.(int); ok {
|
||||||
|
return r, ok
|
||||||
|
} else if r, ok := v.(float64); ok {
|
||||||
|
return int(r), ok
|
||||||
|
} else if r, ok := v.(string); ok {
|
||||||
|
if v, err := strconv.Atoi(r); err != nil {
|
||||||
|
return 0, false
|
||||||
|
} else {
|
||||||
|
return v, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v.(int), f
|
||||||
|
} else {
|
||||||
|
return 0, f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e PlaygroundExtras) GetString(name string) (string, bool) {
|
||||||
|
v, f := e[name]
|
||||||
|
if f {
|
||||||
|
if r, ok := v.(int); ok {
|
||||||
|
return strconv.Itoa(r), ok
|
||||||
|
} else if r, ok := v.(float64); ok {
|
||||||
|
return strconv.FormatFloat(r, 'g', -1, 64), ok
|
||||||
|
} else if r, ok := v.(bool); ok {
|
||||||
|
return strconv.FormatBool(r), ok
|
||||||
|
} else if r, ok := v.(string); ok {
|
||||||
|
return r, ok
|
||||||
|
} else {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "", f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e PlaygroundExtras) GetDuration(name string) (time.Duration, bool) {
|
||||||
|
v, f := e[name]
|
||||||
|
if f {
|
||||||
|
if r, ok := v.(int); ok {
|
||||||
|
return time.Duration(r), ok
|
||||||
|
} else if r, ok := v.(float64); ok {
|
||||||
|
return time.Duration(r), ok
|
||||||
|
} else if r, ok := v.(string); ok {
|
||||||
|
if d, err := time.ParseDuration(r); err != nil {
|
||||||
|
return time.Duration(0), false
|
||||||
|
} else {
|
||||||
|
return d, true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return time.Duration(0), false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return time.Duration(0), f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Playground struct {
|
||||||
|
Id string `json:"id" bson:"id"`
|
||||||
|
Domain string `json:"domain" bson:"domain"`
|
||||||
|
DefaultDinDInstanceImage string `json:"default_dind_instance_image" bson:"default_dind_instance_image"`
|
||||||
|
AvailableDinDInstanceImages []string `json:"available_dind_instance_images" bson:"available_dind_instance_images"`
|
||||||
|
AllowWindowsInstances bool `json:"allow_windows_instances" bson:"allow_windows_instances"`
|
||||||
|
DefaultSessionDuration time.Duration `json:"default_session_duration" bson:"default_session_duration"`
|
||||||
|
L2RouterIP string `json:"l2_router_ip" bson:"l2_router_ip"`
|
||||||
|
Extras PlaygroundExtras `json:"extras" bson:"extras"`
|
||||||
|
}
|
||||||
119
pwd/types/playground_test.go
Normal file
119
pwd/types/playground_test.go
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/twinj/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPlayground_Extras_GetInt(t *testing.T) {
|
||||||
|
p := Playground{
|
||||||
|
Id: uuid.NewV4().String(),
|
||||||
|
Domain: "localhost",
|
||||||
|
DefaultDinDInstanceImage: "franel/dind",
|
||||||
|
AllowWindowsInstances: false,
|
||||||
|
DefaultSessionDuration: time.Hour * 4,
|
||||||
|
Extras: PlaygroundExtras{
|
||||||
|
"intFromInt": 10,
|
||||||
|
"intFromFloat": 32.0,
|
||||||
|
"intFromString": "15",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(p)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
var p2 Playground
|
||||||
|
json.Unmarshal(b, &p2)
|
||||||
|
|
||||||
|
v, found := p2.Extras.GetInt("intFromInt")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, 10, v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetInt("intFromFloat")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, 32, v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetInt("intFromString")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, 15, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlayground_Extras_GetString(t *testing.T) {
|
||||||
|
p := Playground{
|
||||||
|
Id: uuid.NewV4().String(),
|
||||||
|
Domain: "localhost",
|
||||||
|
DefaultDinDInstanceImage: "franel/dind",
|
||||||
|
AllowWindowsInstances: false,
|
||||||
|
DefaultSessionDuration: time.Hour * 4,
|
||||||
|
Extras: PlaygroundExtras{
|
||||||
|
"stringFromInt": 10,
|
||||||
|
"stringFromFloat": 32.3,
|
||||||
|
"stringFromString": "15",
|
||||||
|
"stringFromBool": false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(p)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
var p2 Playground
|
||||||
|
json.Unmarshal(b, &p2)
|
||||||
|
|
||||||
|
v, found := p2.Extras.GetString("stringFromInt")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, "10", v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetString("stringFromFloat")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, "32.3", v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetString("stringFromString")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, "15", v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetString("stringFromBool")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, "false", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlayground_Extras_GetDuration(t *testing.T) {
|
||||||
|
p := Playground{
|
||||||
|
Id: uuid.NewV4().String(),
|
||||||
|
Domain: "localhost",
|
||||||
|
DefaultDinDInstanceImage: "franel/dind",
|
||||||
|
AllowWindowsInstances: false,
|
||||||
|
DefaultSessionDuration: time.Hour * 4,
|
||||||
|
Extras: PlaygroundExtras{
|
||||||
|
"durationFromInt": 10,
|
||||||
|
"durationFromFloat": 32.3,
|
||||||
|
"durationFromString": "4h",
|
||||||
|
"durationFromDuration": time.Hour * 3,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(p)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
var p2 Playground
|
||||||
|
json.Unmarshal(b, &p2)
|
||||||
|
|
||||||
|
v, found := p2.Extras.GetDuration("durationFromInt")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, time.Duration(10), v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetDuration("durationFromFloat")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, time.Duration(32), v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetDuration("durationFromString")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, time.Hour*4, v)
|
||||||
|
|
||||||
|
v, found = p2.Extras.GetDuration("durationFromDuration")
|
||||||
|
assert.True(t, found)
|
||||||
|
assert.Equal(t, time.Hour*3, v)
|
||||||
|
}
|
||||||
@@ -15,4 +15,5 @@ type Session struct {
|
|||||||
ImageName string `json:"image_name" bson:"image_name"`
|
ImageName string `json:"image_name" bson:"image_name"`
|
||||||
Host string `json:"host" bson:"host"`
|
Host string `json:"host" bson:"host"`
|
||||||
UserId string `json:"user_id" bson:"user_id"`
|
UserId string `json:"user_id" bson:"user_id"`
|
||||||
|
PlaygroundId string `json:"playground_id" bson:"playground_id"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type DB struct {
|
|||||||
WindowsInstances map[string]*types.WindowsInstance `json:"windows_instances"`
|
WindowsInstances map[string]*types.WindowsInstance `json:"windows_instances"`
|
||||||
LoginRequests map[string]*types.LoginRequest `json:"login_requests"`
|
LoginRequests map[string]*types.LoginRequest `json:"login_requests"`
|
||||||
Users map[string]*types.User `json:"user"`
|
Users map[string]*types.User `json:"user"`
|
||||||
|
Playgrounds map[string]*types.Playground `json:"playgrounds"`
|
||||||
|
|
||||||
WindowsInstancesBySessionId map[string][]string `json:"windows_instances_by_session_id"`
|
WindowsInstancesBySessionId map[string][]string `json:"windows_instances_by_session_id"`
|
||||||
InstancesBySessionId map[string][]string `json:"instances_by_session_id"`
|
InstancesBySessionId map[string][]string `json:"instances_by_session_id"`
|
||||||
@@ -364,6 +365,25 @@ func (store *storage) UserGet(id string) (*types.User, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (store *storage) PlaygroundPut(playground *types.Playground) error {
|
||||||
|
store.rw.Lock()
|
||||||
|
defer store.rw.Unlock()
|
||||||
|
|
||||||
|
store.db.Playgrounds[playground.Id] = playground
|
||||||
|
|
||||||
|
return store.save()
|
||||||
|
}
|
||||||
|
func (store *storage) PlaygroundGet(id string) (*types.Playground, error) {
|
||||||
|
store.rw.Lock()
|
||||||
|
defer store.rw.Unlock()
|
||||||
|
if playground, found := store.db.Playgrounds[id]; !found {
|
||||||
|
return nil, NotFoundError
|
||||||
|
} else {
|
||||||
|
return playground, nil
|
||||||
|
}
|
||||||
|
return nil, NotFoundError
|
||||||
|
}
|
||||||
|
|
||||||
func (store *storage) load() error {
|
func (store *storage) load() error {
|
||||||
file, err := os.Open(store.path)
|
file, err := os.Open(store.path)
|
||||||
|
|
||||||
@@ -382,6 +402,7 @@ func (store *storage) load() error {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -392,6 +413,19 @@ func (store *storage) load() error {
|
|||||||
file.Close()
|
file.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (store *storage) PlaygroundGetAll() ([]*types.Playground, error) {
|
||||||
|
store.rw.Lock()
|
||||||
|
defer store.rw.Unlock()
|
||||||
|
|
||||||
|
playgrounds := make([]*types.Playground, len(store.db.Playgrounds))
|
||||||
|
i := 0
|
||||||
|
for _, p := range store.db.Playgrounds {
|
||||||
|
playgrounds[i] = p
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return playgrounds, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (store *storage) save() error {
|
func (store *storage) save() error {
|
||||||
file, err := os.Create(store.path)
|
file, err := os.Create(store.path)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ func TestSessionPut(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -65,6 +66,7 @@ func TestSessionGet(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -104,6 +106,7 @@ func TestSessionGetAll(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -169,6 +172,7 @@ func TestInstanceGet(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{expectedInstance.SessionId: []string{expectedInstance.Name}},
|
InstancesBySessionId: map[string][]string{expectedInstance.SessionId: []string{expectedInstance.Name}},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -223,6 +227,7 @@ func TestInstancePut(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{i.SessionId: []string{i.Name}},
|
InstancesBySessionId: map[string][]string{i.SessionId: []string{i.Name}},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -286,6 +291,7 @@ func TestInstanceFindBySessionId(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{i1.SessionId: []string{i1.Name, i2.Name}},
|
InstancesBySessionId: map[string][]string{i1.SessionId: []string{i1.Name, i2.Name}},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -322,6 +328,7 @@ func TestWindowsInstanceGetAll(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{i1.Id: i1, i2.Id: i2},
|
WindowsInstances: map[string]*types.WindowsInstance{i1.Id: i1, i2.Id: i2},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{i1.SessionId: []string{i1.Id, i2.Id}},
|
WindowsInstancesBySessionId: map[string][]string{i1.SessionId: []string{i1.Id, i2.Id}},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -377,6 +384,7 @@ func TestWindowsInstancePut(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{i.Id: i},
|
WindowsInstances: map[string]*types.WindowsInstance{i.Id: i},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{i.SessionId: []string{i.Id}},
|
WindowsInstancesBySessionId: map[string][]string{i.SessionId: []string{i.Id}},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{},
|
ClientsBySessionId: map[string][]string{},
|
||||||
@@ -439,6 +447,7 @@ func TestClientGet(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{c.SessionId: []string{c.Id}},
|
ClientsBySessionId: map[string][]string{c.SessionId: []string{c.Id}},
|
||||||
@@ -493,6 +502,7 @@ func TestClientPut(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{c.SessionId: []string{c.Id}},
|
ClientsBySessionId: map[string][]string{c.SessionId: []string{c.Id}},
|
||||||
@@ -556,6 +566,7 @@ func TestClientFindBySessionId(t *testing.T) {
|
|||||||
WindowsInstances: map[string]*types.WindowsInstance{},
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
LoginRequests: map[string]*types.LoginRequest{},
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
Users: map[string]*types.User{},
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{},
|
||||||
WindowsInstancesBySessionId: map[string][]string{},
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
InstancesBySessionId: map[string][]string{},
|
InstancesBySessionId: map[string][]string{},
|
||||||
ClientsBySessionId: map[string][]string{c1.SessionId: []string{c1.Id, c2.Id}},
|
ClientsBySessionId: map[string][]string{c1.SessionId: []string{c1.Id, c2.Id}},
|
||||||
@@ -581,3 +592,120 @@ func TestClientFindBySessionId(t *testing.T) {
|
|||||||
assert.Subset(t, clients, []*types.Client{c1, c2})
|
assert.Subset(t, clients, []*types.Client{c1, c2})
|
||||||
assert.Len(t, clients, 2)
|
assert.Len(t, clients, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPlaygroundGet(t *testing.T) {
|
||||||
|
p := &types.Playground{Id: "aaabbbccc"}
|
||||||
|
expectedDB := &DB{
|
||||||
|
Sessions: map[string]*types.Session{},
|
||||||
|
Instances: map[string]*types.Instance{},
|
||||||
|
Clients: map[string]*types.Client{},
|
||||||
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{p.Id: p},
|
||||||
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
|
InstancesBySessionId: map[string][]string{},
|
||||||
|
ClientsBySessionId: map[string][]string{},
|
||||||
|
UsersByProvider: map[string]string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpfile, err := ioutil.TempFile("", "pwd")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
encoder := json.NewEncoder(tmpfile)
|
||||||
|
err = encoder.Encode(&expectedDB)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
tmpfile.Close()
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
|
storage, err := NewFileStorage(tmpfile.Name())
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
found, err := storage.PlaygroundGet("aaabbbccc")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, p, found)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlaygroundPut(t *testing.T) {
|
||||||
|
tmpfile, err := ioutil.TempFile("", "pwd")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
tmpfile.Close()
|
||||||
|
os.Remove(tmpfile.Name())
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
|
storage, err := NewFileStorage(tmpfile.Name())
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
p := &types.Playground{Id: "aaabbbccc"}
|
||||||
|
|
||||||
|
err = storage.PlaygroundPut(p)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
expectedDB := &DB{
|
||||||
|
Sessions: map[string]*types.Session{},
|
||||||
|
Instances: map[string]*types.Instance{},
|
||||||
|
Clients: map[string]*types.Client{},
|
||||||
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{p.Id: p},
|
||||||
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
|
InstancesBySessionId: map[string][]string{},
|
||||||
|
ClientsBySessionId: map[string][]string{},
|
||||||
|
UsersByProvider: map[string]string{},
|
||||||
|
}
|
||||||
|
var loadedDB *DB
|
||||||
|
|
||||||
|
file, err := os.Open(tmpfile.Name())
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(file)
|
||||||
|
err = decoder.Decode(&loadedDB)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.EqualValues(t, expectedDB, loadedDB)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlaygroundGetAll(t *testing.T) {
|
||||||
|
p1 := &types.Playground{Id: "aaabbbccc"}
|
||||||
|
p2 := &types.Playground{Id: "dddeeefff"}
|
||||||
|
expectedDB := &DB{
|
||||||
|
Sessions: map[string]*types.Session{},
|
||||||
|
Instances: map[string]*types.Instance{},
|
||||||
|
Clients: map[string]*types.Client{},
|
||||||
|
WindowsInstances: map[string]*types.WindowsInstance{},
|
||||||
|
LoginRequests: map[string]*types.LoginRequest{},
|
||||||
|
Users: map[string]*types.User{},
|
||||||
|
Playgrounds: map[string]*types.Playground{p1.Id: p1, p2.Id: p2},
|
||||||
|
WindowsInstancesBySessionId: map[string][]string{},
|
||||||
|
InstancesBySessionId: map[string][]string{},
|
||||||
|
ClientsBySessionId: map[string][]string{},
|
||||||
|
UsersByProvider: map[string]string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpfile, err := ioutil.TempFile("", "pwd")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
encoder := json.NewEncoder(tmpfile)
|
||||||
|
err = encoder.Encode(&expectedDB)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
tmpfile.Close()
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
|
storage, err := NewFileStorage(tmpfile.Name())
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
found, err := storage.PlaygroundGetAll()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []*types.Playground{p1, p2}, found)
|
||||||
|
}
|
||||||
|
|||||||
@@ -106,3 +106,15 @@ func (m *Mock) UserGet(id string) (*types.User, error) {
|
|||||||
args := m.Called(id)
|
args := m.Called(id)
|
||||||
return args.Get(0).(*types.User), args.Error(1)
|
return args.Get(0).(*types.User), args.Error(1)
|
||||||
}
|
}
|
||||||
|
func (m *Mock) PlaygroundPut(playground *types.Playground) error {
|
||||||
|
args := m.Called(playground)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
func (m *Mock) PlaygroundGet(id string) (*types.Playground, error) {
|
||||||
|
args := m.Called(id)
|
||||||
|
return args.Get(0).(*types.Playground), args.Error(1)
|
||||||
|
}
|
||||||
|
func (m *Mock) PlaygroundGetAll() ([]*types.Playground, error) {
|
||||||
|
args := m.Called()
|
||||||
|
return args.Get(0).([]*types.Playground), args.Error(1)
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,4 +42,8 @@ type StorageApi interface {
|
|||||||
UserFindByProvider(providerName, providerUserId string) (*types.User, error)
|
UserFindByProvider(providerName, providerUserId string) (*types.User, error)
|
||||||
UserPut(user *types.User) error
|
UserPut(user *types.User) error
|
||||||
UserGet(id string) (*types.User, error)
|
UserGet(id string) (*types.User, error)
|
||||||
|
|
||||||
|
PlaygroundPut(playground *types.Playground) error
|
||||||
|
PlaygroundGet(id string) (*types.Playground, error)
|
||||||
|
PlaygroundGetAll() ([]*types.Playground, error)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user