From 50d73cbd716db88cdd99c38cd28054192c429b3a Mon Sep 17 00:00:00 2001 From: Malachy Byrne Date: Fri, 5 May 2023 00:40:18 +0100 Subject: [PATCH 1/3] Added backend for docker management --- src/backend/cmd/main.go | 131 +++++++++++++++++-------------- src/backend/go.mod | 10 +++ src/backend/go.sum | 49 ++++++++++++ src/backend/pkg/docker/docker.go | 107 +++++++++++++++++++++++++ 4 files changed, 240 insertions(+), 57 deletions(-) create mode 100644 src/backend/pkg/docker/docker.go diff --git a/src/backend/cmd/main.go b/src/backend/cmd/main.go index 66c5cd3..67a97a5 100644 --- a/src/backend/cmd/main.go +++ b/src/backend/cmd/main.go @@ -1,41 +1,42 @@ package main import ( - - "database/sql" - _"encoding/json" - "fmt" - "io/ioutil" - "log" - "net/http" - "github.com/dgrijalva/jwt-go" - "golang.org/x/crypto/bcrypt" + "database/sql" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "bytes" + "net/http" + "github.com/dgrijalva/jwt-go" + "golang.org/x/crypto/bcrypt" "github.com/labstack/echo/v4" - "gitlab.computing.dcu.ie/murphg62/2023-ca400-murphg62-byrnm257/src/backend/pkg/database" - _ "golang.org/x/mod/module" + "gitlab.computing.dcu.ie/murphg62/2023-ca400-murphg62-byrnm257/src/backend/pkg/database" + "gitlab.computing.dcu.ie/murphg62/2023-ca400-murphg62-byrnm257/src/backend/pkg/docker" + _ "golang.org/x/mod/module" ) const ( - host = "localhost" - port = 5432 - user = "postgres" - password = "Gcvy4266" - dbname = "Panoptes" + host = "localhost" + port = 5432 + user = "postgres" + password = "Gcvy4266" + dbname = "Panoptes" ) var db, err = database.ConnectDB(host, port, user, password, dbname) var jwtSecret = []byte("fAHr+Hlho9qhCePEuMxLVG2i/1tiEqtocAWkcYRJx0s=") type Schema struct { - Name string `json:"Name"` - Type int `json:"Type"` + Name string `json:"Name"` + Type int `json:"Type"` } type Module struct { - Name string `json:"Name"` - Container string `json:"Container"` + Name string `json:"Name"` + Container string `json:"Container"` } type User struct { @@ -45,44 +46,44 @@ type User struct { func homePage(c echo.Context) error { - return c.String(http.StatusOK, "Welcome to the home page!") + return c.String(http.StatusOK, "Welcome to the home page!") } func getSchema(c echo.Context) error { - key := c.Param("container") + key := c.Param("container") - requestURL := fmt.Sprintf("http://%s/schema", key) - resp, err := http.Get(requestURL) - if err != nil { - log.Fatalf("Request to container failed: %v", err) - } + requestURL := fmt.Sprintf("http://%s/schema", key) + resp, err := http.Get(requestURL) + if err != nil { + log.Fatalf("Request to container failed: %v", err) + } - defer resp.Body.Close() + defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - log.Fatalf("Failed to print Body: %v", err) - } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Failed to print Body: %v", err) + } return c.JSONBlob(http.StatusOK, body) } func getStats(c echo.Context) error { - key := c.Param("container") + key := c.Param("container") - requestURL := fmt.Sprintf("http://%s:8080", key) - resp, err := http.Get(requestURL) - if err != nil { - log.Fatalf("Request to container failed: %v", err) - } + requestURL := fmt.Sprintf("http://%s:8080", key) + resp, err := http.Get(requestURL) + if err != nil { + log.Fatalf("Request to container failed: %v", err) + } - defer resp.Body.Close() + defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - log.Fatalf("Failed to print Body: %v", err) - } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Failed to print Body: %v", err) + } return c.JSONBlob(http.StatusOK, body) } @@ -158,9 +159,9 @@ func LoginUser(db *sql.DB, jwtSecret []byte) echo.HandlerFunc { return err } - if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password)); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid username or password"}) - } + if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password)); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid username or password"}) + } // Generate JWT token token := jwt.New(jwt.SigningMethodHS256) @@ -190,6 +191,21 @@ func LogoutUser() echo.HandlerFunc { } } +func CreateModule(c echo.Context) error { + buf := new(bytes.Buffer) + buf.ReadFrom(c.Request().Body) + var module docker.Module + json.Unmarshal(buf.Bytes(), &module) + mod_id := docker.CreateModule(module) + stmt, err := db.Prepare(`INSERT INTO Module (name, container_name) VALUES ($1, $2);`) + if err != nil { + fmt.Println("lmao") + panic(err) + } + _, err = stmt.Exec(module.Name, mod_id) + return c.NoContent(http.StatusOK) +} + func main() { if err != nil { @@ -199,20 +215,21 @@ func main() { name VARCHAR(64), container_name VARCHAR(64)); - CREATE TABLE IF NOT EXISTS users ( - id SERIAL PRIMARY KEY, - name VARCHAR(64) UNIQUE NOT NULL, - password VARCHAR(255) NOT NULL - ) - `) + CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + name VARCHAR(64) UNIQUE NOT NULL, + password VARCHAR(255) NOT NULL + ) + `) e := echo.New() e.GET("/", homePage) e.GET("/:container/schema", getSchema) e.GET("/:container/stats", getStats) - e.GET("/modules", GetModules(db)) - e.POST("/user/register", RegisterUser(db)) - e.POST("/user/login", LoginUser(db, jwtSecret)) - e.POST("/user/logout", LogoutUser()) + e.GET("/modules", GetModules(db)) + e.POST("/user/register", RegisterUser(db)) + e.POST("/user/login", LoginUser(db, jwtSecret)) + e.POST("/user/logout", LogoutUser()) + e.POST("/create_module", CreateModule) e.Logger.Fatal(e.Start(":10000")) - defer db.Close() + defer db.Close() } diff --git a/src/backend/go.mod b/src/backend/go.mod index aacd066..b727a28 100644 --- a/src/backend/go.mod +++ b/src/backend/go.mod @@ -11,11 +11,20 @@ require ( ) require ( + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/docker/docker v23.0.5+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect @@ -23,5 +32,6 @@ require ( golang.org/x/net v0.9.0 // indirect golang.org/x/sys v0.7.0 // indirect golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/src/backend/go.sum b/src/backend/go.sum index 521cb41..9dd9be5 100644 --- a/src/backend/go.sum +++ b/src/backend/go.sum @@ -1,12 +1,26 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v23.0.5+incompatible h1:DaxtlTJjFSnLOXVNUBU1+6kXGz2lpDoEAH6QoxaSg8k= +github.com/docker/docker v23.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= @@ -20,6 +34,12 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -35,16 +55,33 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -53,10 +90,22 @@ golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/backend/pkg/docker/docker.go b/src/backend/pkg/docker/docker.go new file mode 100644 index 0000000..d6ffc12 --- /dev/null +++ b/src/backend/pkg/docker/docker.go @@ -0,0 +1,107 @@ +package docker + +import ( + "context" + "fmt" + "io" + "io/ioutil" + "os" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + containertypes "github.com/docker/docker/api/types/container" + nattypes "github.com/docker/go-connections/nat" + networktypes "github.com/docker/docker/api/types/network" +) + +type Module struct { + ID string `json:"id"` + Image string `json:"image"` + Name string `json:"name"` + User string `json:"user"` + Env []struct { + Var string `json:"var"` + Val string `json:"val"` + } `json:"env"` + Volumes []struct { + Host string `json:"host"` + Local string `json:"local"` + Tag string `json:"tag"` + } `json:"volumes"` + UrlsAllowed string `json:"urls_allowed"` + InternalAccess bool `json:"internal_access"` +} + +func ContainerConfig(module Module, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkConfig *networktypes.NetworkingConfig) { + config.Image = module.Image + config.Hostname = module.Name + config.User = module.User + + var env []string + for _, e := range module.Env { + v := fmt.Sprintf("%s=%s", e.Var, e.Val) + env = append(env, v) + } + config.Env = env + + var vols []string + for _, v := range module.Volumes { + vol := fmt.Sprintf("%s:%s:%s", v.Host, v.Local, v.Tag) + vols = append(vols, vol) + } + + hostConfig.Binds = vols + exposedPorts := nattypes.PortSet{ + nattypes.Port("8080/tcp"): struct{}{}, + } + config.ExposedPorts = exposedPorts + + networkConfig.EndpointsConfig = map[string]*networktypes.EndpointSettings{ + module.ID: &networktypes.EndpointSettings{}, + } +} + +func CreateModule(module Module) string { + ctx := context.Background() + cli, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + panic(err) + } + + var container containertypes.Config + host := containertypes.HostConfig{} + network := networktypes.NetworkingConfig{} + ContainerConfig(module, &container, &host, &network) + + image_out, err := cli.ImagePull(ctx, module.Image, types.ImagePullOptions{}) + if err != nil { + panic(err) + } + defer image_out.Close() + io.Copy(ioutil.Discard, image_out) + + resp, err := cli.ContainerCreate(ctx, &container, &host, &network, nil, module.Name) + + if err != nil { + panic(err) + } + + if _, err := cli.NetworkInspect(ctx, module.ID, types.NetworkInspectOptions{}); err != nil { + networkConfig := types.NetworkCreate{ + Internal: module.InternalAccess, + } + if _, err := cli.NetworkCreate(ctx, module.ID, networkConfig); err != nil { + panic(err) + } + } + + if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { + panic(err) + } + + if err := cli.NetworkConnect(ctx, module.ID, os.Getenv("hostname"), &networktypes.EndpointSettings{}); err != nil { + panic(err) + } + + return resp.ID +} From 68aebf085e77dbb6117b325f8d44b0a69fe23bda Mon Sep 17 00:00:00 2001 From: Malachy Byrne Date: Fri, 5 May 2023 14:13:46 +0100 Subject: [PATCH 2/3] Modified docker config format sent by frontend --- src/PanoptesFrontend/.gitignore | 2 + src/PanoptesFrontend/Data/ModuleConfig.cs | 13 +++++-- src/PanoptesFrontend/Pages/ModConfig.razor | 45 +++++++++++++++------- src/backend/cmd/main.go | 10 +++-- 4 files changed, 49 insertions(+), 21 deletions(-) create mode 100644 src/PanoptesFrontend/.gitignore diff --git a/src/PanoptesFrontend/.gitignore b/src/PanoptesFrontend/.gitignore new file mode 100644 index 0000000..1c6344d --- /dev/null +++ b/src/PanoptesFrontend/.gitignore @@ -0,0 +1,2 @@ +*.dll +*.cache diff --git a/src/PanoptesFrontend/Data/ModuleConfig.cs b/src/PanoptesFrontend/Data/ModuleConfig.cs index 72ddd2d..83541da 100644 --- a/src/PanoptesFrontend/Data/ModuleConfig.cs +++ b/src/PanoptesFrontend/Data/ModuleConfig.cs @@ -1,5 +1,10 @@ public class ModuleConfig { - public string ImageName {get; set;} - public Dictionary Environment {get; set;} = new Dictionary(); - public Dictionary Volumes {get; set;} = new Dictionary(); -} \ No newline at end of file + public string id {get; set;} + public string image {get; set;} + public string name {get; set;} + public string user {get; set;} = "1000:1000"; + public List> env {get; set;} = new List>{}; + public List> volumes {get; set;} = new List>{}; + public string urls_allowed {get; set;} = "*"; + public bool internal_access {get; set;} = true; +} diff --git a/src/PanoptesFrontend/Pages/ModConfig.razor b/src/PanoptesFrontend/Pages/ModConfig.razor index 4c7930b..bcfe846 100644 --- a/src/PanoptesFrontend/Pages/ModConfig.razor +++ b/src/PanoptesFrontend/Pages/ModConfig.razor @@ -1,5 +1,7 @@ @page "/module-config" @using System.Text.Json +@using System.Text +@using Newtonsoft.Json @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using System.Net; @@ -12,8 +14,14 @@
- - + + + + + + + +
@@ -44,11 +52,11 @@ - @foreach (var kvp in ModuleConfig.Environment) + @for (int i = 0; i < ModuleConfig.env.Count; i++) { - @kvp.Key - @kvp.Value + @ModuleConfig.env[i]["var"] + @ModuleConfig.env[i]["val"] } @@ -79,11 +87,11 @@ - @foreach (var kvp in ModuleConfig.Volumes) + @foreach (Dictionary kvp in ModuleConfig.volumes) { - @kvp.Key - @kvp.Value + @kvp["val"] + @kvp["var"] } @@ -112,14 +120,24 @@ private void AddKeyValuePair1() { - ModuleConfig.Environment.Add(Key1, Value1); + var envs = new Dictionary() + { + { "var", Key1 }, + { "val", Value1 } + }; + ModuleConfig.env.Add(envs); Key1 = ""; Value1 = ""; } private void AddKeyValuePair2() { - ModuleConfig.Volumes.Add(Key2, Value2); + var vols = new Dictionary() + { + { "var", Key2 }, + { "val", Value2 } + }; + ModuleConfig.volumes.Add(vols); Key2 = ""; Value2 = ""; } @@ -127,9 +145,10 @@ private async void SubmitForm() { // Log ModuleConfig object to console and send to backend - var config = JsonSerializer.Serialize(ModuleConfig); + var config = JsonConvert.SerializeObject(ModuleConfig); Console.WriteLine(config); - await httpService.PostAsync("http://localhost:8080/config_module", config); + var payload = new StringContent(config, Encoding.UTF8, "application/json"); + await httpService.PostAsync("http://localhost:10000/create_module", ModuleConfig); } } -} \ No newline at end of file +} diff --git a/src/backend/cmd/main.go b/src/backend/cmd/main.go index 67a97a5..f989b57 100644 --- a/src/backend/cmd/main.go +++ b/src/backend/cmd/main.go @@ -6,7 +6,7 @@ import ( "fmt" "io/ioutil" "log" - "bytes" + //"bytes" "net/http" "github.com/dgrijalva/jwt-go" "golang.org/x/crypto/bcrypt" @@ -192,10 +192,12 @@ func LogoutUser() echo.HandlerFunc { } func CreateModule(c echo.Context) error { - buf := new(bytes.Buffer) - buf.ReadFrom(c.Request().Body) var module docker.Module - json.Unmarshal(buf.Bytes(), &module) + if err := c.Bind(&module); err != nil { + panic(err) + } + s, _ := json.MarshalIndent(module, "", " ") + fmt.Println(string(s)) mod_id := docker.CreateModule(module) stmt, err := db.Prepare(`INSERT INTO Module (name, container_name) VALUES ($1, $2);`) if err != nil { From 6ff59b5f8ae078eda9a098cc152255a06a9dee93 Mon Sep 17 00:00:00 2001 From: Malachy Byrne Date: Fri, 5 May 2023 16:51:07 +0100 Subject: [PATCH 3/3] added tests for module management page --- src/PanoptesTest/ConfigTests.cs | 52 +++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/PanoptesTest/ConfigTests.cs b/src/PanoptesTest/ConfigTests.cs index 3ee554a..43e99c9 100644 --- a/src/PanoptesTest/ConfigTests.cs +++ b/src/PanoptesTest/ConfigTests.cs @@ -7,7 +7,7 @@ using System.Net.Http; public class ModuleConfigTests : TestContext { [Fact] - public void ImageNameInputFieldIsPresent() + public void NameInputFieldIsPresent() { Services.AddSingleton(); // Arrange @@ -16,7 +16,55 @@ public class ModuleConfigTests : TestContext var cut = ctx.RenderComponent(); // Act - var input = cut.Find("input[name='ImageName']"); + var input = cut.Find("input[name='name']"); + + // Assert + Assert.NotNull(input); + } + + [Fact] + public void ImageInputFieldIsPresent() + { + Services.AddSingleton(); + // Arrange + using var ctx = new TestContext(); + ctx.Services.AddSingleton(); + var cut = ctx.RenderComponent(); + + // Act + var input = cut.Find("input[name='image']"); + + // Assert + Assert.NotNull(input); + } + + [Fact] + public void UserInputFieldIsPresent() + { + Services.AddSingleton(); + // Arrange + using var ctx = new TestContext(); + ctx.Services.AddSingleton(); + var cut = ctx.RenderComponent(); + + // Act + var input = cut.Find("input[name='user']"); + + // Assert + Assert.NotNull(input); + } + + [Fact] + public void InternalInputFieldIsPresent() + { + Services.AddSingleton(); + // Arrange + using var ctx = new TestContext(); + ctx.Services.AddSingleton(); + var cut = ctx.RenderComponent(); + + // Act + var input = cut.Find("input[name='internal']"); // Assert Assert.NotNull(input);