*Fix get action *Taking common out of modules * initial glue tests * dynamic docker sock for testing * Stats rewroked to be more encapsulated * Fix of stats gathering in background
This commit is contained in:
parent
722d2a1c86
commit
676ddf2136
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ test:
|
|||||||
go test -v apps/*.go
|
go test -v apps/*.go
|
||||||
go test -v apps/drivers/*.go
|
go test -v apps/drivers/*.go
|
||||||
go test -v detector/*.go
|
go test -v detector/*.go
|
||||||
# go test -v containers/*.go # Doesn't work in Drone right now
|
# env DOCKER_SOCKET="unix:///var/run/docker.sock" go test -v containers/*.go # Doesn't work in Drone right now
|
||||||
|
|
||||||
build:
|
build:
|
||||||
#podman run --rm --privileged -ti -v ${shell pwd}:/srv docker.io/library/golang:1.14-stretch /bin/sh -c "cd /srv && go build"
|
#podman run --rm --privileged -ti -v ${shell pwd}:/srv docker.io/library/golang:1.14-stretch /bin/sh -c "cd /srv && go build"
|
||||||
|
@ -5,8 +5,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
// This is line from GORM documentation that imports database dialect
|
|
||||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
|
||||||
"github.com/rosti-cz/node-api/detector"
|
"github.com/rosti-cz/node-api/detector"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,6 +53,8 @@ type App struct {
|
|||||||
// Datetime of deletion
|
// Datetime of deletion
|
||||||
DeletedAt *time.Time `sql:"index" json:"deleted_at"`
|
DeletedAt *time.Time `sql:"index" json:"deleted_at"`
|
||||||
|
|
||||||
|
// ####################################################
|
||||||
|
// This part is used in app template
|
||||||
// Name of the application
|
// Name of the application
|
||||||
// Example: test_1234
|
// Example: test_1234
|
||||||
Name string `json:"name" gorm:"unique,index,not_null"`
|
Name string `json:"name" gorm:"unique,index,not_null"`
|
||||||
@ -74,6 +74,7 @@ type App struct {
|
|||||||
Memory int `json:"memory"` // Limit in MB
|
Memory int `json:"memory"` // Limit in MB
|
||||||
// Custom labels
|
// Custom labels
|
||||||
Labels []Label `json:"labels" gorm:"foreignkey:AppID"` // username:cx or user_id:1
|
Labels []Label `json:"labels" gorm:"foreignkey:AppID"` // username:cx or user_id:1
|
||||||
|
// ####################################################
|
||||||
|
|
||||||
// Current status of the application (underlaying container)
|
// Current status of the application (underlaying container)
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
package containers
|
package containers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getTestDockerSock() string {
|
||||||
|
dockerSocket := os.Getenv("DOCKER_SOCKET")
|
||||||
|
if dockerSocket == "" {
|
||||||
|
return "unix:///run/user/1000/podman/podman.sock"
|
||||||
|
}
|
||||||
|
return dockerSocket
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetProcesses(t *testing.T) {
|
func TestGetProcesses(t *testing.T) {
|
||||||
driver := Driver{
|
driver := Driver{
|
||||||
//DockerSock: "unix:///run/user/1000/podman/podman.sock",
|
DockerSock: getTestDockerSock(),
|
||||||
DockerSock: "unix:///var/run/docker.sock",
|
|
||||||
BindIPHTTP: "127.0.0.1",
|
BindIPHTTP: "127.0.0.1",
|
||||||
BindIPSSH: "127.0.0.1",
|
BindIPSSH: "127.0.0.1",
|
||||||
}
|
}
|
||||||
|
49
glue/main.go
49
glue/main.go
@ -20,6 +20,7 @@ type Processor struct {
|
|||||||
AppName string
|
AppName string
|
||||||
DB *gorm.DB
|
DB *gorm.DB
|
||||||
SnapshotProcessor *apps.SnapshotProcessor
|
SnapshotProcessor *apps.SnapshotProcessor
|
||||||
|
NodeProcessor *node.Processor
|
||||||
WaitForAppLoops uint // each loop is five seconds
|
WaitForAppLoops uint // each loop is five seconds
|
||||||
DockerSock string
|
DockerSock string
|
||||||
BindIPHTTP string
|
BindIPHTTP string
|
||||||
@ -31,9 +32,7 @@ type Processor struct {
|
|||||||
func (p *Processor) getContainer() (containers.Container, error) {
|
func (p *Processor) getContainer() (containers.Container, error) {
|
||||||
container := containers.Container{}
|
container := containers.Container{}
|
||||||
|
|
||||||
processor := apps.AppsProcessor{
|
processor := p.getAppProcessor()
|
||||||
DB: p.DB,
|
|
||||||
}
|
|
||||||
app, err := processor.Get(p.AppName)
|
app, err := processor.Get(p.AppName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return container, err
|
return container, err
|
||||||
@ -52,9 +51,11 @@ func (p *Processor) getContainer() (containers.Container, error) {
|
|||||||
|
|
||||||
// returns instance of getAppProcessor
|
// returns instance of getAppProcessor
|
||||||
func (p *Processor) getAppProcessor() apps.AppsProcessor {
|
func (p *Processor) getAppProcessor() apps.AppsProcessor {
|
||||||
return apps.AppsProcessor{
|
processor := apps.AppsProcessor{
|
||||||
DB: p.DB,
|
DB: p.DB,
|
||||||
}
|
}
|
||||||
|
processor.Init()
|
||||||
|
return processor
|
||||||
}
|
}
|
||||||
|
|
||||||
// waits until app is ready
|
// waits until app is ready
|
||||||
@ -65,8 +66,12 @@ func (p *Processor) waitForApp() error {
|
|||||||
loops = int(p.WaitForAppLoops)
|
loops = int(p.WaitForAppLoops)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statsProcessor := StatsProcessor{
|
||||||
|
DB: p.DB,
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < loops; i++ {
|
for i := 0; i < loops; i++ {
|
||||||
err := updateState(p.AppName)
|
err := statsProcessor.UpdateState(p.AppName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
time.Sleep(sleepFor)
|
time.Sleep(sleepFor)
|
||||||
continue
|
continue
|
||||||
@ -95,14 +100,16 @@ func (p *Processor) waitForApp() error {
|
|||||||
func (p *Processor) List() (apps.Apps, error) {
|
func (p *Processor) List() (apps.Apps, error) {
|
||||||
appList := apps.Apps{}
|
appList := apps.Apps{}
|
||||||
|
|
||||||
err := gatherStates()
|
statsProcessor := StatsProcessor{
|
||||||
|
DB: p.DB,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := statsProcessor.GatherStates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return appList, fmt.Errorf("backend error: %v", err)
|
return appList, fmt.Errorf("backend error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
processor := apps.AppsProcessor{
|
processor := p.getAppProcessor()
|
||||||
DB: p.DB,
|
|
||||||
}
|
|
||||||
appList, err = processor.List()
|
appList, err = processor.List()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -116,14 +123,16 @@ func (p *Processor) List() (apps.Apps, error) {
|
|||||||
func (p *Processor) Get() (apps.App, error) {
|
func (p *Processor) Get() (apps.App, error) {
|
||||||
app := apps.App{}
|
app := apps.App{}
|
||||||
|
|
||||||
err := updateState(p.AppName)
|
statsProcessor := StatsProcessor{
|
||||||
|
DB: p.DB,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := statsProcessor.UpdateState(p.AppName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return app, err
|
return app, err
|
||||||
}
|
}
|
||||||
|
|
||||||
processor := apps.AppsProcessor{
|
processor := p.getAppProcessor()
|
||||||
DB: p.DB,
|
|
||||||
}
|
|
||||||
app, err = processor.Get(p.AppName)
|
app, err = processor.Get(p.AppName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return app, err
|
return app, err
|
||||||
@ -206,9 +215,7 @@ func (p *Processor) Create(appTemplate apps.App) error {
|
|||||||
// Register registers app without creating a container for it
|
// Register registers app without creating a container for it
|
||||||
// Returns app name and an error
|
// Returns app name and an error
|
||||||
func (p *Processor) Register(appTemplate apps.App) error {
|
func (p *Processor) Register(appTemplate apps.App) error {
|
||||||
processor := apps.AppsProcessor{
|
processor := p.getAppProcessor()
|
||||||
DB: p.DB,
|
|
||||||
}
|
|
||||||
err := processor.New(appTemplate.Name, appTemplate.SSHPort, appTemplate.HTTPPort, appTemplate.Image, appTemplate.CPU, appTemplate.Memory)
|
err := processor.New(appTemplate.Name, appTemplate.SSHPort, appTemplate.HTTPPort, appTemplate.Image, appTemplate.CPU, appTemplate.Memory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if validationError, ok := err.(apps.ValidationError); ok {
|
if validationError, ok := err.(apps.ValidationError); ok {
|
||||||
@ -222,9 +229,7 @@ func (p *Processor) Register(appTemplate apps.App) error {
|
|||||||
|
|
||||||
// Update updates application
|
// Update updates application
|
||||||
func (p *Processor) Update(appTemplate apps.App) error {
|
func (p *Processor) Update(appTemplate apps.App) error {
|
||||||
processor := apps.AppsProcessor{
|
processor := p.getAppProcessor()
|
||||||
DB: p.DB,
|
|
||||||
}
|
|
||||||
app, err := processor.Update(appTemplate.Name, appTemplate.SSHPort, appTemplate.HTTPPort, appTemplate.Image, appTemplate.CPU, appTemplate.Memory)
|
app, err := processor.Update(appTemplate.Name, appTemplate.SSHPort, appTemplate.HTTPPort, appTemplate.Image, appTemplate.CPU, appTemplate.Memory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if validationError, ok := err.(apps.ValidationError); ok {
|
if validationError, ok := err.(apps.ValidationError); ok {
|
||||||
@ -265,9 +270,7 @@ func (p *Processor) Update(appTemplate apps.App) error {
|
|||||||
|
|
||||||
// Delete removes app from the system
|
// Delete removes app from the system
|
||||||
func (p *Processor) Delete() error {
|
func (p *Processor) Delete() error {
|
||||||
processor := apps.AppsProcessor{
|
processor := p.getAppProcessor()
|
||||||
DB: p.DB,
|
|
||||||
}
|
|
||||||
container, err := p.getContainer()
|
container, err := p.getContainer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("ERROR: delete app:", err.Error())
|
log.Println("ERROR: delete app:", err.Error())
|
||||||
@ -486,7 +489,7 @@ func (p *Processor) RemoveLabel(label string) error {
|
|||||||
|
|
||||||
// GetNote returns node's info
|
// GetNote returns node's info
|
||||||
func (p *Processor) GetNode() (*node.Node, error) {
|
func (p *Processor) GetNode() (*node.Node, error) {
|
||||||
node, err := node.GetNodeInfo()
|
node, err := p.NodeProcessor.GetNodeInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
194
glue/main_test.go
Normal file
194
glue/main_test.go
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
package glue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/rosti-cz/node-api/apps"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
// This is line from GORM documentation that imports database dialect
|
||||||
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testDBPath = "file::memory:?cache=shared"
|
||||||
|
|
||||||
|
var testAppTemplate apps.App = apps.App{
|
||||||
|
Name: "test_1234",
|
||||||
|
SSHPort: 10000,
|
||||||
|
HTTPPort: 10001,
|
||||||
|
Image: "harbor.hq.rosti.cz/public/runtime:2022.01-1",
|
||||||
|
CPU: 50,
|
||||||
|
Memory: 256,
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPWD() string {
|
||||||
|
dir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDB() *gorm.DB {
|
||||||
|
db, err := gorm.Open("sqlite3", testDBPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestDockerSock() string {
|
||||||
|
dockerSocket := os.Getenv("DOCKER_SOCKET")
|
||||||
|
if dockerSocket == "" {
|
||||||
|
return "unix:///run/user/1000/podman/podman.sock"
|
||||||
|
}
|
||||||
|
return dockerSocket
|
||||||
|
}
|
||||||
|
|
||||||
|
var processor Processor
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
// This processor is used to test all methods
|
||||||
|
processor = Processor{
|
||||||
|
AppName: testAppTemplate.Name,
|
||||||
|
DB: testDB(),
|
||||||
|
// SnapshotProcessor *apps.SnapshotProcessor
|
||||||
|
DockerSock: getTestDockerSock(),
|
||||||
|
BindIPHTTP: "127.0.0.1",
|
||||||
|
BindIPSSH: "127.0.0.1",
|
||||||
|
AppsPath: path.Join(getPWD(), "tmp/apps"),
|
||||||
|
}
|
||||||
|
|
||||||
|
exitVal := m.Run()
|
||||||
|
|
||||||
|
// We don't care about output here because we can't do anything about it
|
||||||
|
//! If testing fails and this won't be performed you have to remove the test container manually
|
||||||
|
fmt.Println("Removing test container")
|
||||||
|
processor.Delete()
|
||||||
|
|
||||||
|
os.Exit(exitVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorCreate(t *testing.T) {
|
||||||
|
err := processor.Create(testAppTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
processor.Delete()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorList(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorGet(t *testing.T) {
|
||||||
|
err := processor.Create(testAppTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
app, err := processor.Get()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
fmt.Println("State", app.State)
|
||||||
|
|
||||||
|
processor.Delete()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorRegister(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorUpdate(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorDelete(t *testing.T) {
|
||||||
|
err := processor.Create(testAppTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
processor.Delete()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorStop(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorStart(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorRestart(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorUpdateKeys(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorSetPassword(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorProcesses(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorEnableTech(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorRebuild(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorAddLabel(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorRemoveLabel(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorGetNode(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorCreateSnapshot(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorRestoreFromSnapshot(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorListSnapshots(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorListAppsSnapshots(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorListSnapshotsByLabel(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorGetSnapshot(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorGetSnapshotDownloadLink(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorDeleteSnapshot(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessorDeleteAppSnapshots(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
@ -3,16 +3,29 @@ package glue
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
"github.com/rosti-cz/node-api/apps"
|
"github.com/rosti-cz/node-api/apps"
|
||||||
"github.com/rosti-cz/node-api/common"
|
|
||||||
docker "github.com/rosti-cz/node-api/containers"
|
docker "github.com/rosti-cz/node-api/containers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// updateUsage updates various resource usage of the container/app in the database
|
// StatsProcessor covers all methods that are needed
|
||||||
func updateUsage(name string) error {
|
// to gather information about application containers.
|
||||||
|
type StatsProcessor struct {
|
||||||
|
DB *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns instance of getAppProcessor
|
||||||
|
func (s *StatsProcessor) getAppProcessor() apps.AppsProcessor {
|
||||||
processor := apps.AppsProcessor{
|
processor := apps.AppsProcessor{
|
||||||
DB: common.GetDBConnection(),
|
DB: s.DB,
|
||||||
}
|
}
|
||||||
|
processor.Init()
|
||||||
|
return processor
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateUsage updates various resource usage of the container/app in the database
|
||||||
|
func (s *StatsProcessor) UpdateUsage(name string) error {
|
||||||
|
processor := s.getAppProcessor()
|
||||||
|
|
||||||
app, err := processor.Get(name)
|
app, err := processor.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -42,10 +55,8 @@ func updateUsage(name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Updates only container's state. Check current status of the container and saves it into the database.
|
// Updates only container's state. Check current status of the container and saves it into the database.
|
||||||
func updateState(name string) error {
|
func (s *StatsProcessor) UpdateState(name string) error {
|
||||||
processor := apps.AppsProcessor{
|
processor := s.getAppProcessor()
|
||||||
DB: common.GetDBConnection(),
|
|
||||||
}
|
|
||||||
app, err := processor.Get(name)
|
app, err := processor.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -67,17 +78,15 @@ func updateState(name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// gatherStats loops over all applications and calls updateUsage to write various metric into the database.
|
// gatherStats loops over all applications and calls updateUsage to write various metric into the database.
|
||||||
func gatherStats() error {
|
func (s *StatsProcessor) GatherStats() error {
|
||||||
processor := apps.AppsProcessor{
|
processor := s.getAppProcessor()
|
||||||
DB: common.GetDBConnection(),
|
|
||||||
}
|
|
||||||
appList, err := processor.List()
|
appList, err := processor.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, app := range appList {
|
for _, app := range appList {
|
||||||
err := updateUsage(app.Name)
|
err := s.UpdateUsage(app.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("STATS ERROR:", err.Error())
|
log.Println("STATS ERROR:", err.Error())
|
||||||
}
|
}
|
||||||
@ -87,17 +96,15 @@ func gatherStats() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// gatherStates loops over all apps and updates their container state
|
// gatherStates loops over all apps and updates their container state
|
||||||
func gatherStates() error {
|
func (s *StatsProcessor) GatherStates() error {
|
||||||
processor := apps.AppsProcessor{
|
processor := s.getAppProcessor()
|
||||||
DB: common.GetDBConnection(),
|
|
||||||
}
|
|
||||||
appList, err := processor.List()
|
appList, err := processor.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, app := range appList {
|
for _, app := range appList {
|
||||||
err := updateState(app.Name)
|
err := s.UpdateState(app.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("STATE ERROR:", err.Error())
|
log.Println("STATE ERROR:", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -369,6 +369,7 @@ func getNodeInfoHandler(c echo.Context) error {
|
|||||||
BindIPHTTP: config.AppsBindIPHTTP,
|
BindIPHTTP: config.AppsBindIPHTTP,
|
||||||
BindIPSSH: config.AppsBindIPSSH,
|
BindIPSSH: config.AppsBindIPSSH,
|
||||||
AppsPath: config.AppsPath,
|
AppsPath: config.AppsPath,
|
||||||
|
NodeProcessor: &nodeProcessor,
|
||||||
}
|
}
|
||||||
node, err := processor.GetNode()
|
node, err := processor.GetNode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -409,6 +410,7 @@ func metricsHandler(c echo.Context) error {
|
|||||||
BindIPHTTP: config.AppsBindIPHTTP,
|
BindIPHTTP: config.AppsBindIPHTTP,
|
||||||
BindIPSSH: config.AppsBindIPSSH,
|
BindIPSSH: config.AppsBindIPSSH,
|
||||||
AppsPath: config.AppsPath,
|
AppsPath: config.AppsPath,
|
||||||
|
NodeProcessor: &nodeProcessor,
|
||||||
}
|
}
|
||||||
node, err := processor.GetNode()
|
node, err := processor.GetNode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -126,7 +126,12 @@ func listEventHandler(m *nats.Msg, message *RequestMessage) error {
|
|||||||
// Returns one app
|
// Returns one app
|
||||||
func getEventHandler(m *nats.Msg, message *RequestMessage) error {
|
func getEventHandler(m *nats.Msg, message *RequestMessage) error {
|
||||||
processor := glue.Processor{
|
processor := glue.Processor{
|
||||||
|
AppName: message.AppName,
|
||||||
DB: common.GetDBConnection(),
|
DB: common.GetDBConnection(),
|
||||||
|
DockerSock: config.DockerSocket,
|
||||||
|
BindIPHTTP: config.AppsBindIPHTTP,
|
||||||
|
BindIPSSH: config.AppsBindIPSSH,
|
||||||
|
AppsPath: config.AppsPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
app, err := processor.Get()
|
app, err := processor.Get()
|
||||||
@ -597,6 +602,7 @@ func getNodeEventHandler(m *nats.Msg, message *RequestMessage) error {
|
|||||||
BindIPHTTP: config.AppsBindIPHTTP,
|
BindIPHTTP: config.AppsBindIPHTTP,
|
||||||
BindIPSSH: config.AppsBindIPSSH,
|
BindIPSSH: config.AppsBindIPSSH,
|
||||||
AppsPath: config.AppsPath,
|
AppsPath: config.AppsPath,
|
||||||
|
NodeProcessor: &nodeProcessor,
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err := processor.GetNode()
|
node, err := processor.GetNode()
|
||||||
|
38
main.go
38
main.go
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/rosti-cz/node-api/apps"
|
"github.com/rosti-cz/node-api/apps"
|
||||||
"github.com/rosti-cz/node-api/apps/drivers"
|
"github.com/rosti-cz/node-api/apps/drivers"
|
||||||
"github.com/rosti-cz/node-api/common"
|
"github.com/rosti-cz/node-api/common"
|
||||||
|
"github.com/rosti-cz/node-api/glue"
|
||||||
"github.com/rosti-cz/node-api/node"
|
"github.com/rosti-cz/node-api/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ const JSONIndent = " "
|
|||||||
var config common.Config
|
var config common.Config
|
||||||
var nc *nats.Conn
|
var nc *nats.Conn
|
||||||
var snapshotProcessor apps.SnapshotProcessor
|
var snapshotProcessor apps.SnapshotProcessor
|
||||||
|
var nodeProcessor node.Processor
|
||||||
|
|
||||||
func _init() {
|
func _init() {
|
||||||
var err error
|
var err error
|
||||||
@ -52,6 +54,10 @@ func _init() {
|
|||||||
Bucket: config.SnapshotsS3Bucket,
|
Bucket: config.SnapshotsS3Bucket,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeProcessor = node.Processor{
|
||||||
|
DB: common.GetDBConnection(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -66,24 +72,28 @@ func main() {
|
|||||||
t := &Template{}
|
t := &Template{}
|
||||||
|
|
||||||
// Stats loop
|
// Stats loop
|
||||||
// go func() {
|
go func() {
|
||||||
// for {
|
statsProcessor := glue.StatsProcessor{
|
||||||
// log.Println("Stats gathering started")
|
DB: common.GetDBConnection(),
|
||||||
// start := time.Now()
|
}
|
||||||
// err := gatherStats()
|
|
||||||
// if err != nil {
|
for {
|
||||||
// log.Println("LOOP ERROR:", err.Error())
|
log.Println("Stats gathering started")
|
||||||
// }
|
start := time.Now()
|
||||||
// elapsed := time.Since(start)
|
err := statsProcessor.GatherStats()
|
||||||
// log.Printf("Stats gathering elapsed time: %.2fs\n", elapsed.Seconds())
|
if err != nil {
|
||||||
// time.Sleep(300 * time.Second)
|
log.Println("LOOP ERROR:", err.Error())
|
||||||
// }
|
}
|
||||||
// }()
|
elapsed := time.Since(start)
|
||||||
|
log.Printf("Stats gathering elapsed time: %.2fs\n", elapsed.Seconds())
|
||||||
|
time.Sleep(300 * time.Second)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Node stats
|
// Node stats
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
err := node.Log()
|
err := nodeProcessor.Log()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("NODE PERFORMANCE LOG ERROR:", err.Error())
|
log.Println("NODE PERFORMANCE LOG ERROR:", err.Error())
|
||||||
}
|
}
|
||||||
|
35
node/load.go
35
node/load.go
@ -1,23 +1,33 @@
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rosti-cz/node-api/common"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/cpu"
|
"github.com/shirou/gopsutil/cpu"
|
||||||
"github.com/shirou/gopsutil/disk"
|
"github.com/shirou/gopsutil/disk"
|
||||||
"github.com/shirou/gopsutil/load"
|
"github.com/shirou/gopsutil/load"
|
||||||
"github.com/shirou/gopsutil/mem"
|
"github.com/shirou/gopsutil/mem"
|
||||||
|
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
const history = 72 * 3600 / 300 // 3 days, one record every five minutes
|
const history = 72 * 3600 / 300 // 3 days, one record every five minutes
|
||||||
|
|
||||||
func init() {
|
// Processor covers Node related methods for monitoring and calculating performance indexes.
|
||||||
db := common.GetDBConnection()
|
type Processor struct {
|
||||||
db.AutoMigrate(PerformanceLog{})
|
DB *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Processor) Init() {
|
||||||
|
p.DB.AutoMigrate(PerformanceLog{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNodeInfo returns information about this node
|
||||||
|
func (p *Processor) GetNodeInfo() (*Node, error) {
|
||||||
|
node, err := p.Index()
|
||||||
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log creates a record for all important metrics used as
|
// Log creates a record for all important metrics used as
|
||||||
func Log() error {
|
func (p *Processor) Log() error {
|
||||||
performanceLog := PerformanceLog{}
|
performanceLog := PerformanceLog{}
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
@ -45,8 +55,7 @@ func Log() error {
|
|||||||
performanceLog.DiskSpaceUsage = diskUsage.UsedPercent / 100.0
|
performanceLog.DiskSpaceUsage = diskUsage.UsedPercent / 100.0
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
db := common.GetDBConnection()
|
err = p.DB.Create(&performanceLog).Error
|
||||||
err = db.Create(&performanceLog).Error
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -54,13 +63,13 @@ func Log() error {
|
|||||||
// and clean
|
// and clean
|
||||||
// we have to use this stupid approach because DELETE doesn't support ORDER BY and LIMIT
|
// we have to use this stupid approach because DELETE doesn't support ORDER BY and LIMIT
|
||||||
toDeleteLogs := []PerformanceLog{}
|
toDeleteLogs := []PerformanceLog{}
|
||||||
err = db.Order("id DESC").Limit("99").Offset(history).Find(&toDeleteLogs).Error
|
err = p.DB.Order("id DESC").Limit("99").Offset(history).Find(&toDeleteLogs).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, toDeleteLog := range toDeleteLogs {
|
for _, toDeleteLog := range toDeleteLogs {
|
||||||
err = db.Delete(&toDeleteLog).Error
|
err = p.DB.Delete(&toDeleteLog).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -71,7 +80,7 @@ func Log() error {
|
|||||||
|
|
||||||
// Index returns number from 0 to 1 where 0 means least loaded and 1 maximally loaded.
|
// Index returns number from 0 to 1 where 0 means least loaded and 1 maximally loaded.
|
||||||
// It uses history of last 72 hours
|
// It uses history of last 72 hours
|
||||||
func index() (*Node, error) {
|
func (p *Processor) Index() (*Node, error) {
|
||||||
node := Node{
|
node := Node{
|
||||||
Index: 1.0,
|
Index: 1.0,
|
||||||
}
|
}
|
||||||
@ -82,11 +91,9 @@ func index() (*Node, error) {
|
|||||||
return &node, err
|
return &node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
db := common.GetDBConnection()
|
|
||||||
|
|
||||||
logs := []PerformanceLog{}
|
logs := []PerformanceLog{}
|
||||||
|
|
||||||
err = db.Find(&logs).Error
|
err = p.DB.Find(&logs).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &node, err
|
return &node, err
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1 @@
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
// GetNodeInfo returns information about this node
|
|
||||||
func GetNodeInfo() (*Node, error) {
|
|
||||||
node, err := index()
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user