node-api/containers/tools.go

184 lines
3.9 KiB
Go
Raw Normal View History

package containers
2020-07-09 22:27:23 +00:00
import (
"bytes"
2023-04-24 12:19:58 +00:00
"errors"
"fmt"
2020-07-15 21:32:28 +00:00
"log"
2020-07-11 11:04:37 +00:00
"os"
2020-07-09 22:27:23 +00:00
"os/exec"
2020-07-11 11:04:37 +00:00
"path/filepath"
2023-04-24 12:19:58 +00:00
"regexp"
2020-07-09 22:27:23 +00:00
"strconv"
"strings"
"time"
"github.com/rosti-cz/node-api/apps"
2020-07-09 22:27:23 +00:00
)
// Return bytes, inodes occupied by a directory and/or error if there is any
func du(path string) (int, int, error) {
space, inodes := 0, 0
// Occupied space
var out bytes.Buffer
2020-07-15 21:32:28 +00:00
var errOut bytes.Buffer
2020-07-16 21:24:09 +00:00
command := exec.Command("/usr/bin/du", "-b", "-s", path)
2020-07-09 22:27:23 +00:00
command.Stdout = &out
2020-07-15 21:32:28 +00:00
command.Stderr = &errOut
2020-07-09 22:27:23 +00:00
err := command.Run()
if err != nil {
2020-07-15 21:32:28 +00:00
log.Println(errOut.String())
2020-07-09 22:27:23 +00:00
return space, inodes, err
}
fields := strings.Fields(strings.TrimSpace(out.String()))
out.Reset()
2020-07-15 21:32:28 +00:00
errOut.Reset()
2020-07-09 22:27:23 +00:00
if len(fields) == 2 {
space, err = strconv.Atoi(fields[0])
if err != nil {
return space, inodes, err
}
}
// Occupied inodes
2020-07-15 21:32:28 +00:00
command = exec.Command("/usr/bin/du", "--inodes", "-s", path)
2020-07-09 22:27:23 +00:00
command.Stdout = &out
2020-07-15 21:32:28 +00:00
command.Stderr = &errOut
2020-07-09 22:27:23 +00:00
err = command.Run()
if err != nil {
2020-07-15 21:32:28 +00:00
log.Println(errOut.String())
2020-07-09 22:27:23 +00:00
return space, inodes, err
}
fields = strings.Fields(strings.TrimSpace(out.String()))
out.Reset()
2020-07-15 21:32:28 +00:00
errOut.Reset()
2020-07-09 22:27:23 +00:00
if len(fields) == 2 {
2020-07-15 21:32:28 +00:00
inodes, err = strconv.Atoi(fields[0])
2020-07-09 22:27:23 +00:00
if err != nil {
return inodes, inodes, err
}
}
return space, inodes, nil
}
2020-07-11 11:04:37 +00:00
// Removes content of given directory and then the directory itself
2020-07-11 11:04:37 +00:00
func removeDirectory(dir string) error {
d, err := os.Open(dir)
if err != nil {
return err
}
defer d.Close()
names, err := d.Readdirnames(-1)
if err != nil {
return err
}
for _, name := range names {
err = os.RemoveAll(filepath.Join(dir, name))
if err != nil {
return err
}
}
err = os.Remove(filepath.Join(dir))
if err != nil {
return err
}
2020-07-11 11:04:37 +00:00
return nil
}
// CPUMemoryStats returns list of applications with updated CPU and memory usage effectively.
// Sample is number of seconds between two measurements of the CPU usage. More means more precise.
func CPUMemoryStats(applist *[]apps.App, sample int) (*[]apps.App, error) {
if sample <= 0 {
sample = 1
}
containers := []Container{}
for _, app := range *applist {
containers = append(containers, Container{App: &app})
}
startMap := make(map[string]int64)
endMap := make(map[string]int64)
start := time.Now().UnixNano()
for _, container := range containers {
cpu, _, err := container.GetRawResourceStats()
if err != nil {
return nil, err
}
startMap[container.App.Name] = cpu
}
time.Sleep(time.Duration(sample) * time.Second)
for idx, container := range containers {
cpu, memory, err := container.GetRawResourceStats()
if err != nil {
return nil, err
}
endMap[container.App.Name] = cpu
containers[idx].App.MemoryUsage = memory
}
end := time.Now().UnixNano()
difference := (float64(end) - float64(start)) / float64(1000000000)
updatedApps := []apps.App{}
for _, container := range containers {
app := *container.App
app.CPUUsage = (float64(endMap[app.Name]) - float64(startMap[app.Name])) / difference / 10000000.0
updatedApps = append(updatedApps, app)
}
return &updatedApps, nil
}
2023-04-24 12:19:58 +00:00
func getTechAndVersion(symlink string) (*TechInfo, error) {
link, err := os.Readlink(symlink)
2023-04-25 17:11:05 +00:00
if os.IsNotExist(err) {
return &TechInfo{
Tech: "default",
Version: "",
}, nil
}
2023-04-24 12:19:58 +00:00
if err != nil {
return nil, fmt.Errorf("error reading symlink: %w", err)
}
absLink, err := filepath.Abs(link)
if err != nil {
return nil, fmt.Errorf("error getting absolute path: %w", err)
}
2023-04-24 20:42:31 +00:00
absLink = strings.TrimSuffix(absLink, "/bin")
2023-04-24 12:19:58 +00:00
dirName := filepath.Base(absLink)
parts := strings.Split(dirName, "-")
2023-04-24 20:29:59 +00:00
fmt.Println("DEBUG", symlink)
fmt.Println("DEBUG", absLink)
fmt.Println("DEBUG", dirName)
fmt.Println("DEBUG", parts)
2023-04-24 12:19:58 +00:00
if len(parts) < 2 {
2023-04-24 20:29:59 +00:00
return &TechInfo{
Tech: "default",
Version: "",
}, nil
2023-04-24 12:19:58 +00:00
}
re := regexp.MustCompile(`\d+\.\d+\.\d+`)
version := re.FindString(parts[1])
if version == "" {
return nil, errors.New("failed to extract version from symlink")
}
return &TechInfo{
Tech: parts[0],
Version: version,
}, nil
}