1.通过命令行参数获取配置文件地址 2.修改coredump.config中的内容.3使用flag库
This commit is contained in:
@@ -1,25 +1,13 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"coredump-handler/types"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Coreconfig struct {
|
func Init() (types.Coreconfig, error) {
|
||||||
Core_pattern string
|
var config types.Coreconfig
|
||||||
Core_limited string
|
|
||||||
Core__pipe_limit string
|
|
||||||
Socket_path string
|
|
||||||
}
|
|
||||||
type Pipeconfig struct {
|
|
||||||
Save_model int //0为文件保存 1为压缩保存 2为minidump保存
|
|
||||||
File_base_path string
|
|
||||||
Total_file_mem_limit string
|
|
||||||
Containered_sock_path string
|
|
||||||
}
|
|
||||||
|
|
||||||
func Init() (Coreconfig, error) {
|
|
||||||
var config Coreconfig
|
|
||||||
content, err := ioutil.ReadFile("./config.json")
|
content, err := ioutil.ReadFile("./config.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return config, err
|
return config, err
|
||||||
@@ -27,9 +15,9 @@ func Init() (Coreconfig, error) {
|
|||||||
err = json.Unmarshal(content, &config)
|
err = json.Unmarshal(content, &config)
|
||||||
return config, err
|
return config, err
|
||||||
}
|
}
|
||||||
func PipeInit() (Pipeconfig, error) {
|
func PipeInit(config_path string) (types.Pipeconfig, error) {
|
||||||
var config Pipeconfig
|
var config types.Pipeconfig
|
||||||
content, err := ioutil.ReadFile("./pipe-config.json")
|
content, err := ioutil.ReadFile(config_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return config, err
|
return config, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"coredump-handler/config"
|
|
||||||
"coredump-handler/logger"
|
"coredump-handler/logger"
|
||||||
|
"coredump-handler/types"
|
||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func coredumpInit(coreconfig config.Coreconfig) error {
|
func coredumpInit(coreconfig types.Coreconfig) error {
|
||||||
cmd := exec.Command("sysctl", "-w", "kernel.core_pattern='"+coreconfig.Core_pattern+"'")
|
cmd := exec.Command("sysctl", "-w", "kernel.core_pattern='"+coreconfig.Core_pattern+"'")
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -32,7 +32,7 @@ func coredumpInit(coreconfig config.Coreconfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func coredumpHandler(coreconfig config.Coreconfig) error {
|
func coredumpHandler(coreconfig types.Coreconfig) error {
|
||||||
syscall.Unlink(coreconfig.Socket_path)
|
syscall.Unlink(coreconfig.Socket_path)
|
||||||
laddr, err := net.ResolveUnixAddr("unix", coreconfig.Socket_path)
|
laddr, err := net.ResolveUnixAddr("unix", coreconfig.Socket_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -4,13 +4,17 @@ import (
|
|||||||
"archive/zip"
|
"archive/zip"
|
||||||
"context"
|
"context"
|
||||||
"coredump-handler/config"
|
"coredump-handler/config"
|
||||||
|
"coredump-handler/types"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
@@ -19,8 +23,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const chunkSize = 1024 * 1024 * 1024 // 1GB
|
const chunkSize = 1024 * 1024 * 1024 // 1GB
|
||||||
|
var coredump_config types.Coredump_config
|
||||||
|
|
||||||
func isDiskSufficient(pipe_config config.Pipeconfig) (bool, error) {
|
func argsJudge() error {
|
||||||
|
if coredump_config.Initial_ns_pid == "" || coredump_config.Process_ns_pid == "" || coredump_config.Corepipe_config_path == "" || coredump_config.Timestap == 0 || coredump_config.Process_exe_path == "" {
|
||||||
|
err := fmt.Sprintf("Failed to initialize command line parameters. -P=%s -p=%s -E=%s -configpath=%s -t=%d", coredump_config.Initial_ns_pid, coredump_config.Process_ns_pid, coredump_config.Process_exe_path, coredump_config.Corepipe_config_path, coredump_config.Timestap)
|
||||||
|
return errors.New(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func isDiskSufficient(pipe_config types.Pipeconfig) (bool, error) {
|
||||||
percent, err := strconv.ParseFloat(pipe_config.Total_file_mem_limit[:len(pipe_config.Total_file_mem_limit)-1], 64)
|
percent, err := strconv.ParseFloat(pipe_config.Total_file_mem_limit[:len(pipe_config.Total_file_mem_limit)-1], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -43,8 +55,8 @@ func isDiskSufficient(pipe_config config.Pipeconfig) (bool, error) {
|
|||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
func createCoreDumpDir(pipe_config *config.Pipeconfig, args []string) error {
|
func createCoreDumpDir(pipe_config *types.Pipeconfig, args types.Coredump_config) error {
|
||||||
pipe_config.File_base_path = fmt.Sprintf("%s/%s_%s_%s", pipe_config.File_base_path, args[1], args[2], args[3])
|
pipe_config.File_base_path = fmt.Sprintf("%s/%s_%s_%d", pipe_config.File_base_path, args.Initial_ns_pid, args.Process_ns_pid, args.Timestap)
|
||||||
dirName := pipe_config.File_base_path
|
dirName := pipe_config.File_base_path
|
||||||
if _, err := os.Stat(dirName); os.IsNotExist(err) {
|
if _, err := os.Stat(dirName); os.IsNotExist(err) {
|
||||||
// 目录不存在,创建目录
|
// 目录不存在,创建目录
|
||||||
@@ -96,12 +108,16 @@ func getImageId(container_id string, sock_path string) (string, error) {
|
|||||||
}
|
}
|
||||||
return imageRef.Name(), nil
|
return imageRef.Name(), nil
|
||||||
}
|
}
|
||||||
func writeCoreConfig(data string) error {
|
func writeCoreConfig(config types.Coredump_config) error {
|
||||||
err := ioutil.WriteFile("coredump.config", []byte(data), 0666)
|
file, err := os.Create("coredump.config")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encoder := json.NewEncoder(file)
|
||||||
|
err = encoder.Encode(&config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("Wrote %d bytes to file\n", len(data))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func writeCoreDumpToFile() error {
|
func writeCoreDumpToFile() error {
|
||||||
@@ -170,16 +186,22 @@ func compress() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
//切换到config文件路径
|
flag.StringVar(&coredump_config.Initial_ns_pid, "P", "", "initial ns pid")
|
||||||
err := changeDirectory("/root/pipe/corepipe")
|
flag.StringVar(&coredump_config.Process_ns_pid, "p", "", "process ns pid")
|
||||||
|
flag.StringVar(&coredump_config.Process_exe_path, "E", "", "pathname of executable process")
|
||||||
|
flag.StringVar(&coredump_config.Corepipe_config_path, "configpath", "", "configfile's path")
|
||||||
|
flag.Int64Var(&coredump_config.Timestap, "t", 0, "the time of coredump")
|
||||||
|
flag.Parse()
|
||||||
|
coredump_config.Process_exe_path = strings.Replace(coredump_config.Process_exe_path, "!", "/", -1)
|
||||||
|
//判断参数读取是否正确
|
||||||
|
err := argsJudge()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
journal.Print(journal.PriErr, err.Error())
|
journal.Print(journal.PriErr, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//读取config文件并初始化
|
//读取config文件并初始化
|
||||||
pipe_config, err := config.PipeInit()
|
pipe_config, err := config.PipeInit(coredump_config.Corepipe_config_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
journal.Print(journal.PriErr, err.Error())
|
journal.Print(journal.PriErr, err.Error())
|
||||||
return
|
return
|
||||||
@@ -190,13 +212,8 @@ func main() {
|
|||||||
journal.Print(journal.PriErr, err.Error())
|
journal.Print(journal.PriErr, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//判断参数传入是否符合要求
|
|
||||||
if len(os.Args) < 4 {
|
|
||||||
journal.Print(journal.PriErr, "parameter passing exception")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//创建存储coredump内容文件夹
|
//创建存储coredump内容文件夹
|
||||||
err = createCoreDumpDir(&pipe_config, os.Args)
|
err = createCoreDumpDir(&pipe_config, coredump_config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
journal.Print(journal.PriErr, err.Error())
|
journal.Print(journal.PriErr, err.Error())
|
||||||
return
|
return
|
||||||
@@ -208,17 +225,16 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//查找发生coredump进程对应的container id
|
//查找发生coredump进程对应的container id
|
||||||
container_id, err := getContainerId(os.Args[1])
|
container_id, err := getContainerId(coredump_config.Initial_ns_pid)
|
||||||
//根据查找到的container id查找对应的image name
|
//根据查找到的container id查找对应的image name
|
||||||
var image_id string
|
|
||||||
if err == nil && len(container_id) != 0 {
|
if err == nil && len(container_id) != 0 {
|
||||||
image_id, err = getImageId(container_id, pipe_config.Containered_sock_path)
|
coredump_config.Image_id, err = getImageId(container_id, pipe_config.Containered_sock_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
journal.Print(journal.PriInfo, err.Error())
|
journal.Print(journal.PriInfo, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//将image name写入coredump config
|
//将image name写入coredump config
|
||||||
err = writeCoreConfig(image_id)
|
err = writeCoreConfig(coredump_config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
journal.Print(journal.PriInfo, err.Error())
|
journal.Print(journal.PriInfo, err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,278 +1,189 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"coredump-handler/config"
|
"coredump-handler/types"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"os/exec"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsMemorySufficient(t *testing.T) {
|
func TestArgsJudge(t *testing.T) {
|
||||||
type input struct {
|
var coredump_config types.Coredump_config
|
||||||
pipe_config config.Pipeconfig
|
coredump_config.Initial_ns_pid = "123"
|
||||||
}
|
coredump_config.Process_ns_pid = "456"
|
||||||
tests := []struct {
|
coredump_config.Process_exe_path = "/path/to/executable"
|
||||||
name string
|
coredump_config.Corepipe_config_path = "/path/to/config"
|
||||||
input input
|
coredump_config.Timestap = 1618332579
|
||||||
want bool
|
|
||||||
wantErr bool
|
err := argsJudge()
|
||||||
}{
|
assert.Nil(t, err)
|
||||||
{
|
|
||||||
name: "memory is sufficient",
|
// missing Initial_ns_pid
|
||||||
input: input{
|
coredump_config.Initial_ns_pid = ""
|
||||||
pipe_config: config.Pipeconfig{
|
err = argsJudge()
|
||||||
Total_file_mem_limit: "50%",
|
assert.NotNil(t, err)
|
||||||
},
|
coredump_config.Initial_ns_pid = "123"
|
||||||
},
|
|
||||||
want: true,
|
// missing Process_ns_pid
|
||||||
wantErr: false,
|
coredump_config.Process_ns_pid = ""
|
||||||
},
|
err = argsJudge()
|
||||||
{
|
assert.NotNil(t, err)
|
||||||
name: "memory is not sufficient",
|
coredump_config.Process_ns_pid = "456"
|
||||||
input: input{
|
|
||||||
pipe_config: config.Pipeconfig{
|
// missing Corepipe_config_path
|
||||||
Total_file_mem_limit: "0.001%",
|
coredump_config.Corepipe_config_path = ""
|
||||||
},
|
err = argsJudge()
|
||||||
},
|
assert.NotNil(t, err)
|
||||||
want: false,
|
coredump_config.Corepipe_config_path = "/path/to/config"
|
||||||
wantErr: false,
|
|
||||||
},
|
// missing Timestap
|
||||||
{
|
coredump_config.Timestap = 0
|
||||||
name: "invalid memory limit",
|
err = argsJudge()
|
||||||
input: input{
|
assert.NotNil(t, err)
|
||||||
pipe_config: config.Pipeconfig{
|
coredump_config.Timestap = 1618332579
|
||||||
Total_file_mem_limit: "invalid",
|
|
||||||
},
|
// missing Process_exe_path
|
||||||
},
|
coredump_config.Process_exe_path = ""
|
||||||
want: false,
|
err = argsJudge()
|
||||||
wantErr: true,
|
assert.NotNil(t, err)
|
||||||
},
|
coredump_config.Process_exe_path = "/path/to/executable"
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
func TestIsDiskSufficient(t *testing.T) {
|
||||||
got, err := isDiskSufficient(tt.input.pipe_config)
|
pipe_config := types.Pipeconfig{
|
||||||
if (err != nil) != tt.wantErr {
|
Total_file_mem_limit: "50%",
|
||||||
t.Errorf("isMemorySufficient() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if got != tt.want {
|
|
||||||
t.Errorf("isMemorySufficient() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
// create a temp file and set limit to 100%
|
||||||
|
file, err := ioutil.TempFile("", "")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(file.Name())
|
||||||
|
pipe_config.File_base_path = file.Name()
|
||||||
|
pipe_config.Total_file_mem_limit = "100%"
|
||||||
|
flag, err := isDiskSufficient(pipe_config)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.False(t, flag)
|
||||||
|
|
||||||
|
// set limit to 0%
|
||||||
|
pipe_config.Total_file_mem_limit = "0%"
|
||||||
|
flag, err = isDiskSufficient(pipe_config)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateCoreDumpDir(t *testing.T) {
|
func TestCreateCoreDumpDir(t *testing.T) {
|
||||||
type input struct {
|
pipe_config := types.Pipeconfig{
|
||||||
pipe_config *config.Pipeconfig
|
File_base_path: "/tmp",
|
||||||
args []string
|
|
||||||
}
|
}
|
||||||
tests := []struct {
|
err := createCoreDumpDir(&pipe_config, coredump_config)
|
||||||
name string
|
assert.Nil(t, err)
|
||||||
input input
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "directory does not exist",
|
|
||||||
input: input{
|
|
||||||
pipe_config: &config.Pipeconfig{
|
|
||||||
File_base_path: "/tmp",
|
|
||||||
},
|
|
||||||
args: []string{"", "pid", "arg2", "arg3"},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "directory already exists",
|
|
||||||
input: input{
|
|
||||||
pipe_config: &config.Pipeconfig{
|
|
||||||
File_base_path: "/tmp",
|
|
||||||
},
|
|
||||||
args: []string{"", "pid", "arg2", "arg3"},
|
|
||||||
},
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
err := createCoreDumpDir(tt.input.pipe_config, tt.input.args)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("createCoreDumpDir() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChangeDirectory(t *testing.T) {
|
// try to create same directory again should return an error
|
||||||
type input struct {
|
err = createCoreDumpDir(&pipe_config, coredump_config)
|
||||||
dir string
|
assert.NotNil(t, err)
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input input
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "change directory successfully",
|
|
||||||
input: input{
|
|
||||||
dir: "/root",
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "fail to change directory",
|
|
||||||
input: input{
|
|
||||||
dir: "/invalid",
|
|
||||||
},
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
err := changeDirectory(tt.input.dir)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("changeDirectory() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContainerId(t *testing.T) {
|
func TestGetContainerId(t *testing.T) {
|
||||||
type input struct {
|
pid := "1"
|
||||||
pid string
|
container_id, err := getContainerId(pid)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("getContainerId() error = %v", err)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
if len(container_id) == 0 {
|
||||||
name string
|
t.Errorf("getContainerId() = %v, want not empty string", container_id)
|
||||||
input input
|
|
||||||
want string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "get container id successfully",
|
|
||||||
input: input{
|
|
||||||
pid: strconv.Itoa(os.Getpid()),
|
|
||||||
},
|
|
||||||
want: "",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "fail to get container id",
|
|
||||||
input: input{
|
|
||||||
pid: "invalid",
|
|
||||||
},
|
|
||||||
want: "",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := getContainerId(tt.input.pid)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("getContainerId() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(got) == "" {
|
|
||||||
t.Errorf("getContainerId() got empty string")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetImageId(t *testing.T) {
|
func TestGetImageId(t *testing.T) {
|
||||||
type input struct {
|
container_id := "123456"
|
||||||
container_id string
|
sock_path := "/var/run/containerd.sock"
|
||||||
sock_path string
|
image_id, err := getImageId(container_id, sock_path)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("getImageId() error = %v", err)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
if len(image_id) == 0 {
|
||||||
name string
|
t.Errorf("getImageId() = %v, want not empty string", image_id)
|
||||||
input input
|
|
||||||
want string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "get image id successfully",
|
|
||||||
input: input{
|
|
||||||
container_id: "invalid",
|
|
||||||
sock_path: "/run/k3s/containerd/containerd.sock",
|
|
||||||
},
|
|
||||||
want: "",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := getImageId(tt.input.container_id, tt.input.sock_path)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("getImageId() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(got) == "" {
|
|
||||||
t.Errorf("getImageId() got empty string")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWriteCoreConfig(t *testing.T) {
|
func TestWriteCoreConfig(t *testing.T) {
|
||||||
type input struct {
|
config := types.Coredump_config{
|
||||||
data string
|
Initial_ns_pid: "1",
|
||||||
|
Process_ns_pid: "2",
|
||||||
|
Process_exe_path: "/bin/bash",
|
||||||
|
Corepipe_config_path: "/tmp/config.yaml",
|
||||||
|
Timestap: 12345678,
|
||||||
}
|
}
|
||||||
tests := []struct {
|
err := writeCoreConfig(config)
|
||||||
name string
|
if err != nil {
|
||||||
input input
|
t.Errorf("writeCoreConfig() error = %v", err)
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "write core config successfully",
|
|
||||||
input: input{
|
|
||||||
data: "test data",
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
defer os.Remove("coredump.config")
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
}
|
||||||
err := writeCoreConfig(tt.input.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
func TestWriteCoreDumpToFile(t *testing.T) {
|
||||||
t.Errorf("writeCoreConfig() error = %v, wantErr %v", err, tt.wantErr)
|
cmd := exec.Command("echo", "test")
|
||||||
}
|
cmdReader, err := cmd.StdoutPipe()
|
||||||
content, err := ioutil.ReadFile("coredump.config")
|
if err != nil {
|
||||||
if err != nil {
|
t.Errorf("WriteCoreDumpToFile() error = %v", err)
|
||||||
t.Error("failed to read file")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !bytes.Equal(content, []byte(tt.input.data)) {
|
|
||||||
t.Errorf("writeCoreConfig() content = %v, want = %v", string(content), tt.input.data)
|
|
||||||
}
|
|
||||||
os.Remove("coredump.config")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
scanner := bufio.NewScanner(cmdReader)
|
||||||
|
go func() {
|
||||||
|
for scanner.Scan() {
|
||||||
|
fmt.Printf("reading output: %s\n", scanner.Text())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err = cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("WriteCoreDumpToFile() error = %v", err)
|
||||||
|
}
|
||||||
|
err = writeCoreDumpToFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("WriteCoreDumpToFile() error = %v", err)
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadFile("coredump.info")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("WriteCoreDumpToFile() error = %v", err)
|
||||||
|
}
|
||||||
|
expected := "test\n"
|
||||||
|
if string(b) != expected {
|
||||||
|
t.Errorf("WriteCoreDumpToFile() got = %v, want = %v", string(b), expected)
|
||||||
|
}
|
||||||
|
defer os.Remove("coredump.info")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompress(t *testing.T) {
|
func TestCompress(t *testing.T) {
|
||||||
tests := []struct {
|
cmd := exec.Command("echo", "test")
|
||||||
name string
|
cmdReader, err := cmd.StdoutPipe()
|
||||||
wantErr bool
|
if err != nil {
|
||||||
}{
|
t.Errorf("compress() error = %v", err)
|
||||||
{
|
|
||||||
name: "compress successfully",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
scanner := bufio.NewScanner(cmdReader)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
go func() {
|
||||||
err := compress()
|
for scanner.Scan() {
|
||||||
if (err != nil) != tt.wantErr {
|
fmt.Printf("reading output: %s\n", scanner.Text())
|
||||||
t.Errorf("compress() error = %v, wantErr %v", err, tt.wantErr)
|
}
|
||||||
}
|
}()
|
||||||
// Check if the compressed file exists
|
err = cmd.Start()
|
||||||
if _, err := os.Stat("coredump.info.zip"); os.IsNotExist(err) {
|
if err != nil {
|
||||||
t.Errorf("compress() failed to create compressed file")
|
t.Errorf("compress() error = %v", err)
|
||||||
} else {
|
|
||||||
os.Remove("coredump.info.zip")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
err = compress()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("compress() error = %v", err)
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadFile("coredump.info.zip")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("compress() error = %v", err)
|
||||||
|
}
|
||||||
|
expected := []byte{80, 75, 3, 4, 20, 0, 8, 8, 8, 0, 170, 114, 38, 99, 102, 0, 0, 0, 102, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 101, 115, 116, 10, 0, 82, 105, 105, 90, 85, 50, 84, 110, 88, 70, 90, 65, 48, 108, 108, 81, 0, 116, 157, 80, 10, 128, 163, 239, 120, 53, 2, 190, 127, 7, 98, 131, 137, 51, 189, 206, 149, 14, 54, 126, 254, 152, 119, 177, 209, 155, 201, 23, 37, 4, 72, 113, 39, 46, 179, 144, 106, 184, 44, 251, 47, 88, 97, 2, 141, 11, 129, 71, 109, 187, 124, 32, 63, 22, 111, 181, 59, 30, 58, 184, 40, 203, 205, 3, 113, 165, 117, 232, 6, 228, 240, 132, 94, 137, 43, 95, 218, 221, 90, 203, 173, 43, 92, 216, 226, 65, 118, 222, 208, 59, 185, 250, 56, 70, 63, 135, 72, 44, 250, 215, 59, 36, 139, 74, 75, 112, 0, 0, 0}
|
||||||
|
if !bytes.Equal(b, expected) {
|
||||||
|
t.Errorf("compress() got = %v, want = %v", b, expected)
|
||||||
|
}
|
||||||
|
defer os.Remove("coredump.info.zip")
|
||||||
}
|
}
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -5,6 +5,7 @@ go 1.20
|
|||||||
require (
|
require (
|
||||||
github.com/containerd/containerd v1.7.0
|
github.com/containerd/containerd v1.7.0
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0
|
github.com/coreos/go-systemd/v22 v22.5.0
|
||||||
|
github.com/stretchr/testify v1.8.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -18,6 +19,7 @@ require (
|
|||||||
github.com/containerd/ttrpc v1.2.1 // indirect
|
github.com/containerd/ttrpc v1.2.1 // indirect
|
||||||
github.com/containerd/typeurl/v2 v2.1.0 // indirect
|
github.com/containerd/typeurl/v2 v2.1.0 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||||
github.com/go-logr/logr v1.2.3 // indirect
|
github.com/go-logr/logr v1.2.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
@@ -37,6 +39,7 @@ require (
|
|||||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
|
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
|
||||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||||
@@ -50,4 +53,5 @@ require (
|
|||||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
||||||
google.golang.org/grpc v1.53.0 // indirect
|
google.golang.org/grpc v1.53.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -134,6 +134,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
@@ -244,6 +245,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
22
types/types.go
Normal file
22
types/types.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
type Coreconfig struct {
|
||||||
|
Core_pattern string
|
||||||
|
Core_limited string
|
||||||
|
Core__pipe_limit string
|
||||||
|
Socket_path string
|
||||||
|
}
|
||||||
|
type Pipeconfig struct {
|
||||||
|
Save_model int //0为文件保存 1为压缩保存 2为minidump保存
|
||||||
|
File_base_path string
|
||||||
|
Total_file_mem_limit string
|
||||||
|
Containered_sock_path string
|
||||||
|
}
|
||||||
|
type Coredump_config struct {
|
||||||
|
Initial_ns_pid string
|
||||||
|
Process_ns_pid string
|
||||||
|
Process_exe_path string
|
||||||
|
Timestap int64
|
||||||
|
Corepipe_config_path string
|
||||||
|
Image_id string
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user