diff --git a/apps/types.go b/apps/types.go index e04fe18..dee31f4 100644 --- a/apps/types.go +++ b/apps/types.go @@ -67,6 +67,9 @@ type App struct { // Unique: true // Example: 10002 HTTPPort int `json:"http_port"` + // Port of the application inside the container. Default is 0 which means default by the image. + // But it has to be between 1024 and 65536 with exception of 8000. + AppPort int `json:"app_port"` // Runtime image Image string `json:"image"` // Number of CPUs ticks assigned, 100 means one CPU, 200 are two @@ -117,6 +120,10 @@ func (a *App) Validate() []string { errors = append(errors, "HTTP port has to be between 1 and 65536") } + if a.AppPort != 0 && ((a.AppPort < 1024 && a.AppPort > 65536) || a.AppPort == 8000) { + errors = append(errors, "App port has to be between 1024 and 65536 with exception of 8000") + } + if a.Image == "" { errors = append(errors, "image cannot be empty") } diff --git a/containers/types.go b/containers/types.go index 2b83854..1d28872 100644 --- a/containers/types.go +++ b/containers/types.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "path" + "strconv" "strings" "github.com/rosti-cz/node-api/apps" @@ -230,6 +231,29 @@ func (c *Container) SetPassword(password string) error { return err } +// SetAppPort changes application port in the container +func (c *Container) SetAppPort(port int) error { + driver := c.getDriver() + + _, err := driver.Exec( + c.App.Name, + []string{ + "sed", + "-i", + "s+proxy_pass[ ]*http://127.0.0.1:8080/;+proxy_pass http://127.0.0.1:" + strconv.Itoa(port) + "/;+g", + "/srv/conf/nginx.d/app.conf", + }, + "", + []string{}, + false, + ) + if err != nil { + return err + } + + return err +} + // SetFileContent uploads text into a file inside the container. It's greate for uploading SSH keys. // The method creates the diretory where the file is located and sets mode of the final file func (c *Container) SetFileContent(filename string, text string, mode string) error { @@ -307,6 +331,47 @@ func (c *Container) GetProcessList() ([]Process, error) { return processes, nil } +// Restarts supervisord process +func (c *Container) RestartProcess(name string) error { + driver := c.getDriver() + + _, err := driver.Exec(c.App.Name, []string{"supervisorctl", "restart", name}, "", []string{}, false) + return err +} + +// Starts supervisord process +func (c *Container) StartProcess(name string) error { + driver := c.getDriver() + + _, err := driver.Exec(c.App.Name, []string{"supervisorctl", "start", name}, "", []string{}, false) + return err +} + +// Stops supervisord process +func (c *Container) StopProcess(name string) error { + driver := c.getDriver() + + _, err := driver.Exec(c.App.Name, []string{"supervisorctl", "stop", name}, "", []string{}, false) + return err +} + +// Reread supervisord config +func (c *Container) ReloadSupervisor() error { + driver := c.getDriver() + + _, err := driver.Exec(c.App.Name, []string{"supervisorctl", "reread"}, "", []string{}, false) + if err != nil { + return err + } + + _, err = driver.Exec(c.App.Name, []string{"supervisorctl", "update"}, "", []string{}, false) + if err != nil { + return err + } + + return err +} + // GetSystemProcesses return list of running system processes func (c *Container) GetSystemProcesses() ([]string, error) { driver := c.getDriver() diff --git a/glue/main.go b/glue/main.go index 53ccfdb..b55fcc4 100644 --- a/glue/main.go +++ b/glue/main.go @@ -231,6 +231,24 @@ func (p *Processor) Create(appTemplate apps.App) error { } } + // Changes port of the app hosted inside the container + if appTemplate.AppPort != 0 { + err = p.waitForApp() + if err != nil { + return err + } + + err = container.SetAppPort(appTemplate.AppPort) + if err != nil { + return err + } + + err = container.RestartProcess("nginx") + if err != nil { + return err + } + } + err = container.Start() return err } diff --git a/handlers_nats.go b/handlers_nats.go index 2ff2e51..b8678d6 100644 --- a/handlers_nats.go +++ b/handlers_nats.go @@ -160,7 +160,7 @@ func getEventHandler(m *nats.Msg, message *RequestMessage) error { return err } -// Returns one app fast whicn mean with no immediate status update +// Returns one app fast which means with no immediate status update func fastGetEventHandler(m *nats.Msg, message *RequestMessage) error { processor := glue.Processor{ AppName: message.AppName, @@ -632,8 +632,6 @@ func listOrphansEventHandler(m *nats.Msg, message *RequestMessage) error { /* getNodeEventHandler returns info about the node including performance index - - */ func getNodeEventHandler(m *nats.Msg, message *RequestMessage) error { processor := glue.Processor{ @@ -677,7 +675,7 @@ func getNodeEventHandler(m *nats.Msg, message *RequestMessage) error { /* createSnapshotEventHandler create snapshot of given application -Uses appName from the message struct +# Uses appName from the message struct Payload: no payload needed Response: notification when it's done or error @@ -743,7 +741,7 @@ func restoreFromSnapshotEventHandler(m *nats.Msg, message *RequestMessage) error /* listSnapshotsEventHandler returns list of snapshots related to a single application -Uses appName from the message +# Uses appName from the message Payload: no payload needed Response: replies with list of snapshots or an error message @@ -955,7 +953,7 @@ func deleteSnapshotEventHandler(m *nats.Msg, message *RequestMessage) error { /* deleteAppSnapshotsEventHandler deletes all snapshots related to a single application -Uses appName from the message struct +# Uses appName from the message struct Payload: no payload needed Response: notification when it's done or error