Skip to content

Commit

Permalink
Merge pull request #490 from village-way/main
Browse files Browse the repository at this point in the history
change node-agent to golang version to adapt for glibc 2.17
  • Loading branch information
kosmos-robot authored Apr 26, 2024
2 parents ef3b9bc + f2316cd commit 0cabcf9
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 43 deletions.
22 changes: 21 additions & 1 deletion cmd/kubenest/node-agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,27 @@ COPY . .

RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential gcc && \
pip install --no-cache-dir -r requirements.txt
pip install --no-cache-dir -r requirements.txt && \
apt-get install -y pwgen && \
WEB_USER=agent && \
WEB_PASS=$(pwgen -y 12 1) && \
sed -i "s/{{WEB_USER}}/$WEB_USER/g" agent.env && \
sed -i "s/{{WEB_PASS}}/$WEB_PASS/g" agent.env


RUN pip install pyinstaller && \
pyinstaller --onefile app.py

FROM golang:latest AS build-go
WORKDIR /app
COPY go/* .

RUN go mod tidy && \
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o node-agent app.go

RUN openssl req -x509 -sha256 -new -nodes -days 3650 -newkey rsa:2048 -keyout key.pem -out cert.pem -subj "/C=CN/ST=JiangSu/L=SuZhou/O=Kosmos/OU=Kosmos/CN=kosmos.io"


FROM ubuntu:latest as release-env
WORKDIR /app

Expand All @@ -20,6 +36,10 @@ RUN apt-get update && apt-get install -y rsync
# copy install file to container
COPY . .
COPY --from=build-env /app/dist/app /app
COPY --from=build-env /app/agent.env /app
COPY --from=build-go /app/node-agent /app
COPY --from=build-go /app/cert.pem /app
COPY --from=build-go /app/key.pem /app

# install command
CMD ["bash", "/app/install.sh", "/app"]
2 changes: 2 additions & 0 deletions cmd/kubenest/node-agent/agent.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
WEB_USER={{WEB_USER}}
WEB_PASS={{WEB_PASS}}
10 changes: 9 additions & 1 deletion cmd/kubenest/node-agent/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ spec:
image: cis-hub-huabei-3.cmecloud.cn/node-agent/node-agent:latest
securityContext:
privileged: true
command: [ "/bin/bash", "-c", "rsync -avz /app/ /host-path/ && cp /app/node-agent.service /host-systemd/node-agent.service" ]
env:
- name: WEB_USER
value: {{update when you deploy}}
- name: WEB_PASS
value: {{update when you deploy}}
command: ["/bin/bash"]
args:
- "-c"
- "sed -i 's/^WEB_USER=.*/WEB_USER=$(WEB_USER)/' /app/agent.env && sed -i 's/^WEB_PASS=.*/WEB_PASS=$(WEB_PASS)/' /app/agent.env && rsync -avz /app/ /host-path/ && cp /app/node-agent.service /host-systemd/node-agent.service "
volumeMounts:
- mountPath: /host-path
name: node-agent
Expand Down
91 changes: 56 additions & 35 deletions cmd/kubenest/node-agent/go/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"errors"
"flag"
"fmt"
"log"
"net/http"
"net/url"
"os"
Expand All @@ -19,6 +18,7 @@ import (
"time"

"github.com/gorilla/websocket"
"github.com/sirupsen/logrus"
)

var (
Expand All @@ -27,21 +27,42 @@ var (
keyFile = flag.String("key", "key.pem", "SSL key file")
user = flag.String("user", "", "Username for authentication")
password = flag.String("password", "", "Password for authentication")
log = logrus.New()
)

var upgrader = websocket.Upgrader{} // use default options

func init() {
log.Out = os.Stdout

file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err == nil {
log.Out = file
} else {
log.Info("Failed to log to file, using default stderr")
}
log.SetLevel(logrus.InfoLevel)
}
func main() {
flag.Parse()
log.SetFlags(log.LstdFlags | log.Lshortfile)
if len(*user) == 0 || len(*password) == 0 {
*user = os.Getenv("WEB_USER")
*password = os.Getenv("WEB_PASS")
if len(*user) == 0 || len(*password) == 0 {
flag.Usage()
log.Fatal("-user and -password are required")
if *user == "" {
_user := os.Getenv("WEB_USER")
if _user != "" {
*user = _user
}
}

if *password == "" {
_password := os.Getenv("WEB_PASS")
if _password != "" {
*password = _password
}
}
if len(*user) == 0 || len(*password) == 0 {
flag.Usage()
log.Errorf("-user and -password are required %s %s", *user, *password)
return
}
start(*addr, *certFile, *keyFile, *user, *password)
}

Expand Down Expand Up @@ -77,14 +98,14 @@ func start(addr, certFile, keyFile, user, password string) {

conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
log.Errorf("http upgrade to websocket failed : %v", err)
return
}
defer conn.Close()

u, err := url.Parse(r.RequestURI)
if err != nil {
log.Print("parse uri:", err)
log.Errorf("parse uri: %s, %v", r.RequestURI, err)
return
}
queryParams := u.Query()
Expand All @@ -103,7 +124,7 @@ func start(addr, certFile, keyFile, user, password string) {
}
})

log.Printf("Starting server on %s", addr)
log.Infof("Starting server on %s", addr)
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS12,
}
Expand All @@ -115,39 +136,39 @@ func start(addr, certFile, keyFile, user, password string) {
ReadHeaderTimeout: 10 * time.Second,
}

log.Fatal(server.ListenAndServeTLS("", ""))
log.Errorf("failed to start server %v", server.ListenAndServeTLS("", ""))
}

func handleUpload(conn *websocket.Conn, params url.Values) {
fileName := params.Get("file_name")
filePath := params.Get("file_path")
log.Printf("Uploading file name %s, file path %s", fileName, filePath)
log.Infof("Uploading file name %s, file path %s", fileName, filePath)
defer conn.Close()
if len(fileName) != 0 && len(filePath) != 0 {
// mkdir
err := os.MkdirAll(filePath, 0775)
if err != nil {
log.Print("mkdir:", err)
log.Errorf("mkdir: %s %v", filePath, err)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseInternalServerErr, fmt.Sprintf("failed to make directory: %v", err)))
return
}
file := filepath.Join(filePath, fileName)
// check if the file already exists
if _, err := os.Stat(file); err == nil {
log.Printf("File %s already exists", file)
log.Infof("File %s already exists", file)
timestamp := time.Now().Format("2006-01-02-150405000")
bakFilePath := fmt.Sprintf("%s_%s_bak", file, timestamp)
err = os.Rename(file, bakFilePath)
if err != nil {
log.Printf("failed to rename file: %v", err)
log.Errorf("failed to rename file: %v", err)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseInternalServerErr, fmt.Sprintf("failed to rename file: %v", err)))
return
}
}
// create file with append
fp, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Printf("failed to open file: %v", err)
log.Errorf("failed to open file: %v", err)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseInternalServerErr, fmt.Sprintf("failed to open file: %v", err)))
return
}
Expand All @@ -156,20 +177,20 @@ func handleUpload(conn *websocket.Conn, params url.Values) {
for {
_, data, err := conn.ReadMessage()
if err != nil {
log.Printf("failed to read message : %s", err)
log.Errorf("failed to read message : %s", err)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseInternalServerErr, fmt.Sprintf("failed to read message: %v", err)))
return
}
// check if the file end
if string(data) == "EOF" {
log.Printf("finish file data transfer %s", file)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, fmt.Sprintf("finish file data transfer: %v", "EOF")))
log.Infof("finish file data transfer %s", file)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, fmt.Sprintf("%d", 0)))
return
}
// data to file
_, err = fp.Write(data)
if err != nil {
log.Printf("failed to write data to file : %s", err)
log.Errorf("failed to write data to file : %s", err)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseInternalServerErr, fmt.Sprintf("failed write data to file: %v", err)))
return
}
Expand All @@ -181,22 +202,22 @@ func handleUpload(conn *websocket.Conn, params url.Values) {
func handleCmd(conn *websocket.Conn, params url.Values) {
command := params.Get("command")
if command == "" {
log.Printf("No command specified %v", params)
log.Warnf("No command specified %v", params)
_ = conn.WriteMessage(websocket.TextMessage, []byte("No command specified"))
return
}

cmd := exec.Command("sh", "-c", command)
out, err := cmd.CombinedOutput()
if err != nil {
log.Printf("failed to execute command : %v", err)
log.Warnf("failed to execute command : %v", err)
_ = conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
} else {
_ = conn.WriteMessage(websocket.TextMessage, out)
}
exitCode := cmd.ProcessState.ExitCode()
log.Printf("Command finished with exit code %d", exitCode)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, fmt.Sprintf("Exit Code: %d", exitCode)))
log.Infof("Command finished with exit code %d", exitCode)
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, fmt.Sprintf("%d", exitCode)))
}

func handleScript(conn *websocket.Conn, params url.Values, command []string) {
Expand All @@ -208,30 +229,30 @@ func handleScript(conn *websocket.Conn, params url.Values, command []string) {
// Write data to a temporary file
tempFile, err := os.CreateTemp("", "script_*")
if err != nil {
log.Printf("Error creating temporary file: %v", err)
log.Errorf("Error creating temporary file: %v", err)
return
}
defer os.Remove(tempFile.Name()) // Clean up temporary file
defer tempFile.Close()
tempFilefp, err := os.OpenFile(tempFile.Name(), os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Printf("Error opening temporary file: %v", err)
log.Errorf("Error opening temporary file: %v", err)
}
for {
// Read message from WebSocket client
_, data, err := conn.ReadMessage()
if err != nil {
log.Printf("failed to read message : %s", err)
log.Errorf("failed to read message : %s", err)
break
}
if string(data) == "EOF" {
log.Printf("finish file data transfer %s", tempFile.Name())
log.Infof("finish file data transfer %s", tempFile.Name())
break
}

// Write received data to the temporary file
if _, err := tempFilefp.Write(data); err != nil {
log.Printf("Error writing data to temporary file: %v", err)
log.Errorf("Error writing data to temporary file: %v", err)
continue
}
}
Expand All @@ -243,20 +264,20 @@ func handleScript(conn *websocket.Conn, params url.Values, command []string) {
cmd := exec.Command(executeCmd[0], executeCmd[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Printf("Error obtaining command output pipe: %v", err)
log.Warnf("Error obtaining command output pipe: %v", err)
}
defer stdout.Close()

if err := cmd.Start(); err != nil {
log.Printf("Error starting command: %v", err)
log.Warnf("Error starting command: %v", err)
}

// processOutput
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
data := scanner.Bytes()
log.Printf("%s", data)
log.Warnf("%s", data)
_ = conn.WriteMessage(websocket.TextMessage, data)
}
}()
Expand All @@ -265,9 +286,9 @@ func handleScript(conn *websocket.Conn, params url.Values, command []string) {
if err := cmd.Wait(); err != nil {
var exitError *exec.ExitError
if errors.As(err, &exitError) {
log.Printf("Command exited with non-zero status: %v", exitError)
log.Warnf("Command exited with non-zero status: %v", exitError)
}
}
exitCode := cmd.ProcessState.ExitCode()
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, fmt.Sprintf("Exit Code: %d", exitCode)))
_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, fmt.Sprintf("%d", exitCode)))
}
5 changes: 2 additions & 3 deletions cmd/kubenest/node-agent/go/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"crypto/tls"
"encoding/base64"
"fmt"
"log"
"net/http"
"net/url"
"os"
Expand Down Expand Up @@ -33,8 +32,8 @@ func init() {
_, filename, _, _ := runtime.Caller(0)
currentDir = filepath.Dir(filename)
parentDir = filepath.Dir(currentDir)
_ = os.Setenv("WEB_USER", "admin")
_ = os.Setenv("WEB_PASS", "eiqu&ahr3sohW5ee")
_ = os.Setenv("WEB_USER", "")
_ = os.Setenv("WEB_PASS", "")
username = os.Getenv("WEB_USER")
pass = os.Getenv("WEB_PASS")
testAddr = "127.0.0.1:5678"
Expand Down
13 changes: 13 additions & 0 deletions cmd/kubenest/node-agent/go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module github.com/kosmos.io/kubenest/node-agent

go 1.22.1

require (
github.com/gorilla/websocket v1.5.1
github.com/sirupsen/logrus v1.9.3
)

require (
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
)
20 changes: 20 additions & 0 deletions cmd/kubenest/node-agent/go/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
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/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
6 changes: 3 additions & 3 deletions cmd/kubenest/node-agent/node-agent.service
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ After=network.target
User=root
Group=root
WorkingDirectory=/srv/node-agent
Environment="WEB_USER=admin"
Environment="WEB_PASS=bich_oosh2zoh6Oh"
EnvironmentFile=-/srv/node-agent/agent.env
#./app: error while loading shared libraries: libz.so.1: failed to map segment from shared object
Environment="TMPDIR=/srv/node-agent"
#ExecStartPre=-/usr/bin/pip3 install -r /srv/node-agent/requirements.txt
#ExecStart=/usr/bin/env python3 /srv/node-agent/app.py
ExecStart=/srv/node-agent/app --user admin --password 'bich_oosh2zoh6Oh'
#ExecStart=/srv/node-agent/app
ExecStart=/srv/node-agent/node-agent
Restart=on-failure
RestartSec=5

Expand Down
Loading

0 comments on commit 0cabcf9

Please sign in to comment.