Compare commits
184 Commits
38bc72b684
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 7015dc99d6 | |||
| df56a542a1 | |||
| 46dd289c28 | |||
| 43b5aee48b | |||
| 592e00b98b | |||
| 92432fcd83 | |||
| a844bed056 | |||
| 2ddbae07b2 | |||
| 4d6665b64a | |||
| 99e1007012 | |||
| 9632dc7755 | |||
| a60dee1645 | |||
| 7fe5090efa | |||
| e9370513c2 | |||
| 387d4f3ea8 | |||
| e5984b3342 | |||
| f174a165fe | |||
| a112f20cb8 | |||
| 97fc64be81 | |||
| 7ae391b599 | |||
| f5e491325f | |||
| 2fa02374fd | |||
| 380586fb73 | |||
| da37ed11cd | |||
| 3ab055008c | |||
| 71e80d2908 | |||
| 12a0f9d2b1 | |||
| 016f459252 | |||
| 030fa658f5 | |||
| 3c96921703 | |||
| 6f444e0187 | |||
| 3eaad85453 | |||
| 401cfa8b84 | |||
| 5e4799ff55 | |||
| 86e14fbd23 | |||
| fb3886e2e4 | |||
| 95d6741389 | |||
| fdb534c5e0 | |||
| dfcb78b70c | |||
| 4e928f3426 | |||
| d546f2340d | |||
| bad563dce7 | |||
| 62494fb052 | |||
| eb86c0a073 | |||
| 9d4718592d | |||
| dcc94d2609 | |||
| f45558483e | |||
| 01940222b6 | |||
| d03f02a44f | |||
| 27dd9226e9 | |||
| 00fa08a739 | |||
| ccfa9e4be3 | |||
| 68a5876fd8 | |||
| 33181f1717 | |||
| 6e0bd71c80 | |||
| 75992472f3 | |||
| ee1459d760 | |||
| 3913c6cdcf | |||
| 2744a0a990 | |||
| 1d3266bbaf | |||
| 023a2a5194 | |||
| 6eaa856688 | |||
| afa270c9a0 | |||
| ad3382db89 | |||
| e1e2f3c087 | |||
| cf4b458a4b | |||
| 72b88b194f | |||
| cfd6e23384 | |||
| 6416c27230 | |||
| 2ae42d0b08 | |||
| d4cd792950 | |||
| 84543f9a31 | |||
| 1a404e5361 | |||
| d18fe3e3a1 | |||
| b2ff0e8ffc | |||
| 3208eba280 | |||
| 882d35d604 | |||
| ba72262d50 | |||
| 8d764c8d18 | |||
| 299a0a2bd3 | |||
| 5c765fe32f | |||
| 394466e216 | |||
| 61d2fbf709 | |||
| d43b83e761 | |||
| 432cc68024 | |||
| 22148f8ae7 | |||
| 282ef95ab0 | |||
| 5b0b977a39 | |||
| 2985e0fdaf | |||
| b8c1e97ab8 | |||
| c9fecf55de | |||
| 15ab1c9e7c | |||
| b6b8aa0794 | |||
| 64ca01c3a7 | |||
| 5798e77a6c | |||
| c5e2bc203a | |||
| 3ace1be27a | |||
| 3dc121bc71 | |||
| 849973c449 | |||
| d1a192159b | |||
| 7a5696961f | |||
| 4d9a25dd6b | |||
| 9bd09509c8 | |||
| 1b57e9f87e | |||
| 4667d351a8 | |||
| 571f0d76df | |||
| 15dd1e544c | |||
| 45ab15d345 | |||
| 02db65e06f | |||
| a8821b694b | |||
| 5429d3d90f | |||
| cf46888b6a | |||
| 6a35d7b1fe | |||
| d04dd5b05d | |||
| d3442be5dc | |||
| 06bc095ea4 | |||
| da47d7c587 | |||
| d464812cf8 | |||
| fa8b78efed | |||
| 9b0aa4d640 | |||
| cacbc1008a | |||
| 6d319f2fa1 | |||
| 01b4782e78 | |||
| 72e94ccfc3 | |||
| d17c53c79c | |||
| 9590de2e00 | |||
| 58897522a7 | |||
| 06b390815c | |||
| 3d3020f827 | |||
| 9947835ba1 | |||
| 30ff0a4b27 | |||
| c98023cc8b | |||
| 3278bca32f | |||
| bdc3e19718 | |||
| 61a98247d8 | |||
| 3f2ea5cee3 | |||
| a8548fffe2 | |||
| f58db1ec09 | |||
| 1c1f9f748a | |||
| 279c9f47f0 | |||
| 46aedbe767 | |||
| 96ee2a4627 | |||
| 2e4b7811db | |||
| 3add5d9355 | |||
| 20b2df1fc5 | |||
| 4cec01609a | |||
| 43da9424f0 | |||
| c4c0f86947 | |||
| 838b3a2194 | |||
| 93c13ba92f | |||
| ed5b4c06e9 | |||
| c1847ee3e1 | |||
| d490188bd2 | |||
| ac355d32b4 | |||
| 26b12fad72 | |||
| faefd8cfca | |||
| 5f1b23ed80 | |||
| 5c00ff73d7 | |||
| b14ad791df | |||
| 471d07a188 | |||
| 153a9e50ca | |||
| fa5a612173 | |||
| 6719d9b6c1 | |||
| 06c7fbd32d | |||
| 1d525eb7cf | |||
| 18e7ee0afa | |||
| 5326e26a8c | |||
| ae783aabaf | |||
| 1d87ef3501 | |||
| cff643310b | |||
| 9b9c3eaa4d | |||
| 2f30d4cbc0 | |||
| 3161afd091 | |||
| 18e7cbf75e | |||
| 49921d44ce | |||
| 10555ba61a | |||
| 28d8fc4149 | |||
| c4c157e2f8 | |||
| 383f846934 | |||
| 53a385d018 | |||
| 11ea571b6e | |||
| 566a4067ab | |||
| 8289018fd6 | |||
| d1efb92f52 |
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,7 @@
|
||||
go-ayo/
|
||||
*.log
|
||||
*.exe
|
||||
houston
|
||||
houston.zip
|
||||
config.json
|
||||
.vscode/
|
||||
/data
|
||||
|
||||
711
client/client.go
711
client/client.go
@ -2,87 +2,155 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"repositories.action2quare.com/ayo/go-ayo/logger"
|
||||
"github.com/djherbis/times"
|
||||
"repositories.action2quare.com/ayo/gocommon"
|
||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
"repositories.action2quare.com/ayo/houston/shared"
|
||||
"repositories.action2quare.com/ayo/houston/shared/protos"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
sigar "github.com/cloudfoundry/gosigar"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type runcommand struct {
|
||||
Exec string `json:"exec"`
|
||||
Args []string `json:"args"`
|
||||
Version string `json:"version"`
|
||||
AutoRestart bool `json:"auto_restart"`
|
||||
OutputLogFile string `json:"logfile"`
|
||||
}
|
||||
|
||||
type easyruncommand runcommand
|
||||
|
||||
func (t *runcommand) UnmarshalJSON(b []byte) error {
|
||||
easy := easyruncommand{
|
||||
Version: "latest",
|
||||
AutoRestart: true,
|
||||
}
|
||||
if err := json.Unmarshal(b, &easy); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = runcommand(easy)
|
||||
return nil
|
||||
}
|
||||
|
||||
type clientConfig struct {
|
||||
GrpcAddress string `json:"grpc_server_address"`
|
||||
HttpAddress string `json:"http_server_address"`
|
||||
StorageRoot string `json:"storage_path"`
|
||||
MetricNamespace string `json:"metric_namespace"`
|
||||
ConstLabels map[string]string `json:"metric_const_labels"`
|
||||
Autorun map[string]runcommand `json:"autorun"`
|
||||
}
|
||||
|
||||
var autorun = flagx.String("autorun", "", "")
|
||||
|
||||
type outerconfig struct {
|
||||
Houston *struct {
|
||||
Client clientConfig `json:"client"`
|
||||
} `json:"houston"`
|
||||
}
|
||||
|
||||
func loadClientConfig() (clientConfig, error) {
|
||||
var oc outerconfig
|
||||
err := gocommon.LoadConfig[outerconfig](&oc)
|
||||
if err != nil {
|
||||
logger.Println(err)
|
||||
return clientConfig{}, err
|
||||
}
|
||||
|
||||
return oc.Houston.Client, nil
|
||||
}
|
||||
|
||||
type HoustonClient interface {
|
||||
SetReportMetrics(map[string]float32)
|
||||
Shutdown()
|
||||
Start()
|
||||
}
|
||||
|
||||
type bufferStack struct {
|
||||
pool [5][]byte
|
||||
cursor int32
|
||||
}
|
||||
|
||||
func (bs *bufferStack) pop() []byte {
|
||||
pos := atomic.LoadInt32(&bs.cursor)
|
||||
for !atomic.CompareAndSwapInt32(&bs.cursor, pos, pos+1) {
|
||||
pos = atomic.LoadInt32(&bs.cursor)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
bs.pool[pos] = nil
|
||||
}()
|
||||
|
||||
curbuf := bs.pool[pos]
|
||||
if curbuf == nil {
|
||||
curbuf = make([]byte, 1024)
|
||||
}
|
||||
return curbuf
|
||||
}
|
||||
|
||||
func (bs *bufferStack) push(x []byte) {
|
||||
pos := atomic.AddInt32(&bs.cursor, -1)
|
||||
bs.pool[pos] = x
|
||||
}
|
||||
var seq = int32(1)
|
||||
|
||||
type procmeta struct {
|
||||
cmd *exec.Cmd
|
||||
name string
|
||||
version string
|
||||
state protos.ProcessState
|
||||
stdin io.WriteCloser
|
||||
logUploadChan chan *shared.UploadRequest
|
||||
buffers bufferStack
|
||||
id int32
|
||||
cmd *exec.Cmd
|
||||
name string
|
||||
args []string
|
||||
version string
|
||||
verpath string
|
||||
recover bool
|
||||
state int32
|
||||
stdin io.WriteCloser
|
||||
logfile string
|
||||
keepLatest bool
|
||||
}
|
||||
|
||||
func (pm *procmeta) isState(s protos.ProcessState) bool {
|
||||
return atomic.LoadInt32(&pm.state) == int32(s)
|
||||
}
|
||||
|
||||
func (pm *procmeta) getState() protos.ProcessState {
|
||||
return protos.ProcessState(atomic.LoadInt32(&pm.state))
|
||||
}
|
||||
|
||||
func (pm *procmeta) setState(s protos.ProcessState) {
|
||||
atomic.StoreInt32(&pm.state, int32(s))
|
||||
}
|
||||
|
||||
type uploadRequest struct {
|
||||
logFile string
|
||||
name string
|
||||
version string
|
||||
}
|
||||
|
||||
type houstonClient struct {
|
||||
client *grpc.ClientConn
|
||||
childProcs []*procmeta
|
||||
extraMetrics unsafe.Pointer // map[string]float32
|
||||
deploys map[string][]*protos.VersionAndArgs
|
||||
shutdownFunc context.CancelFunc
|
||||
exitChan chan *exec.Cmd
|
||||
httpAddr string
|
||||
timestamp string
|
||||
}
|
||||
|
||||
func bToMb(b uint64) uint32 {
|
||||
return uint32(b / 1024 / 1024)
|
||||
childProcs []*procmeta
|
||||
extraMetrics unsafe.Pointer // map[string]float32
|
||||
deploys map[string][]*protos.VersionAndArgs
|
||||
shutdownFunc context.CancelFunc
|
||||
ctx context.Context
|
||||
operationChan chan *protos.OperationQueryResponse
|
||||
exitChan chan *exec.Cmd
|
||||
clientChan chan *grpc.ClientConn
|
||||
uploadChan chan uploadRequest
|
||||
timestamp string
|
||||
wg sync.WaitGroup
|
||||
config clientConfig
|
||||
version string
|
||||
standalone bool
|
||||
siblingProcIndex map[string]uint64
|
||||
}
|
||||
|
||||
func unmarshal[T any](val *T, src map[string]string) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
logger.Error(r)
|
||||
}
|
||||
}()
|
||||
|
||||
argval := reflect.ValueOf(val)
|
||||
for i := 0; i < argval.Elem().Type().NumField(); i++ {
|
||||
if !argval.Elem().Type().Field(i).IsExported() {
|
||||
@ -92,47 +160,94 @@ func unmarshal[T any](val *T, src map[string]string) {
|
||||
if argval.Elem().Field(i).CanInt() {
|
||||
num, _ := strconv.ParseInt(arg, 10, 0)
|
||||
argval.Elem().Field(i).SetInt(num)
|
||||
} else if argval.Elem().Field(i).Kind() == reflect.Array || argval.Elem().Field(i).Kind() == reflect.Slice {
|
||||
conv := strings.Split(arg, "\n")
|
||||
argval.Elem().Field(i).Set(reflect.ValueOf(conv))
|
||||
} else if argval.Elem().Field(i).Kind() == reflect.Bool {
|
||||
bv, _ := strconv.ParseBool(arg)
|
||||
argval.Elem().Field(i).SetBool(bv)
|
||||
} else {
|
||||
argval.Elem().Field(i).SetString(arg)
|
||||
}
|
||||
}
|
||||
logger.Println("operation receive :", argval.Elem().Type().Name(), *val)
|
||||
}
|
||||
|
||||
func gatherDeployedPrograms(name string) []*protos.VersionAndArgs {
|
||||
var rawvers []*protos.VersionAndArgs
|
||||
if vers, err := os.ReadDir(path.Join("./", name)); err == nil {
|
||||
type version_args_ts struct {
|
||||
*protos.VersionAndArgs
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
func gatherDeployedPrograms(storageRoot, name string) (out []*protos.VersionAndArgs) {
|
||||
var rawvers []version_args_ts
|
||||
targetPath := path.Join(storageRoot, name)
|
||||
if vers, err := os.ReadDir(targetPath); err == nil {
|
||||
for _, ver := range vers {
|
||||
if ver.IsDir() {
|
||||
args := lastExecutionArgs(path.Join(name, ver.Name()))
|
||||
rawvers = append(rawvers, &protos.VersionAndArgs{
|
||||
Version: ver.Name(),
|
||||
Args: args,
|
||||
fi, _ := ver.Info()
|
||||
args := lastExecutionArgs(path.Join(targetPath, ver.Name()))
|
||||
rawvers = append(rawvers, version_args_ts{
|
||||
VersionAndArgs: &protos.VersionAndArgs{
|
||||
Version: ver.Name(),
|
||||
Args: args,
|
||||
},
|
||||
modTime: fi.ModTime(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(rawvers, func(i, j int) bool {
|
||||
leftParsed := shared.ParseVersionString(rawvers[i].Version)
|
||||
rightParsed := shared.ParseVersionString(rawvers[j].Version)
|
||||
return shared.CompareVersionString(leftParsed, rightParsed) < 0
|
||||
return rawvers[i].modTime.After(rawvers[j].modTime)
|
||||
})
|
||||
return rawvers
|
||||
|
||||
for _, v := range rawvers {
|
||||
out = append(out, v.VersionAndArgs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (hc *houstonClient) makeOperationQueryRequest() *protos.OperationQueryRequest {
|
||||
hn, _ := os.Hostname()
|
||||
procs := make([]*protos.ProcessDescription, 0, len(hc.childProcs))
|
||||
var procs []*protos.ProcessDescription
|
||||
var deploys []*protos.DeployedVersions
|
||||
|
||||
var selfname string
|
||||
var selfargs []string
|
||||
if hc.standalone {
|
||||
selfname = path.Base(filepath.ToSlash(os.Args[0]))
|
||||
selfargs = os.Args[1:]
|
||||
} else {
|
||||
selfname = "houston"
|
||||
selfargs = []string{}
|
||||
}
|
||||
|
||||
if len(path.Ext(selfname)) > 0 {
|
||||
selfname = selfname[:len(selfname)-len(path.Ext(selfname))]
|
||||
}
|
||||
|
||||
procs = append(procs, &protos.ProcessDescription{
|
||||
Name: selfname,
|
||||
Args: selfargs,
|
||||
Version: hc.version,
|
||||
State: protos.ProcessState_Running,
|
||||
Pid: int32(os.Getpid()),
|
||||
})
|
||||
deploys = append(deploys, &protos.DeployedVersions{
|
||||
Name: selfname,
|
||||
Versions: []*protos.VersionAndArgs{
|
||||
{Version: hc.version, Args: selfargs},
|
||||
},
|
||||
})
|
||||
|
||||
for _, child := range hc.childProcs {
|
||||
procs = append(procs, &protos.ProcessDescription{
|
||||
Name: child.name,
|
||||
Args: child.cmd.Args,
|
||||
Version: child.version,
|
||||
State: child.state,
|
||||
State: child.getState(),
|
||||
Pid: int32(child.cmd.Process.Pid),
|
||||
})
|
||||
}
|
||||
|
||||
var deploys []*protos.DeployedVersions
|
||||
for name, prog := range hc.deploys {
|
||||
deploys = append(deploys, &protos.DeployedVersions{
|
||||
Name: name,
|
||||
@ -140,19 +255,30 @@ func (hc *houstonClient) makeOperationQueryRequest() *protos.OperationQueryReque
|
||||
})
|
||||
}
|
||||
|
||||
hn, _ := os.Hostname()
|
||||
return &protos.OperationQueryRequest{
|
||||
Hostname: hn,
|
||||
Procs: procs,
|
||||
Deploys: deploys,
|
||||
Hostname: hn,
|
||||
PublicIp: os.Getenv("PUBIP"),
|
||||
PrivateIp: os.Getenv("PRVIP"),
|
||||
Procs: procs,
|
||||
Deploys: deploys,
|
||||
}
|
||||
}
|
||||
|
||||
func NewClient(grpcAddr string, httpAddr string) (HoustonClient, error) {
|
||||
client, err := grpc.Dial(grpcAddr, grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
func NewClient(standalone bool) (HoustonClient, error) {
|
||||
clientConfig, err := loadClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(clientConfig.GrpcAddress) == 0 {
|
||||
return nil, errors.New("client.grpc_server_address is missing")
|
||||
}
|
||||
|
||||
if len(clientConfig.HttpAddress) == 0 {
|
||||
return nil, errors.New("client.http_server_address is missing")
|
||||
}
|
||||
|
||||
exefile, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -163,73 +289,108 @@ func NewClient(grpcAddr string, httpAddr string) (HoustonClient, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sp, err := os.Stat(clientConfig.StorageRoot)
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
err = os.MkdirAll(clientConfig.StorageRoot, 0775)
|
||||
}
|
||||
} else if !sp.IsDir() {
|
||||
err = errors.New(clientConfig.StorageRoot + " is not directory")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deploys := make(map[string][]*protos.VersionAndArgs)
|
||||
if dirs, err := os.ReadDir("./"); err == nil {
|
||||
if dirs, err := os.ReadDir(clientConfig.StorageRoot); err == nil {
|
||||
for _, dir := range dirs {
|
||||
if dir.IsDir() {
|
||||
flagf := path.Join(dir.Name(), "@houston")
|
||||
flagf := path.Join(clientConfig.StorageRoot, dir.Name(), "@houston")
|
||||
if _, err := os.Stat(flagf); !os.IsNotExist(err) {
|
||||
deploys[dir.Name()] = gatherDeployedPrograms(dir.Name())
|
||||
deploys[dir.Name()] = gatherDeployedPrograms(clientConfig.StorageRoot, dir.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ver, _ := os.ReadFile("@version")
|
||||
if len(ver) == 0 {
|
||||
ver = []byte("0.0.0")
|
||||
}
|
||||
|
||||
hc := &houstonClient{
|
||||
client: client,
|
||||
extraMetrics: unsafe.Pointer(&map[string]float32{}),
|
||||
deploys: deploys,
|
||||
httpAddr: httpAddr,
|
||||
timestamp: exefi.ModTime().String(),
|
||||
config: clientConfig,
|
||||
clientChan: make(chan *grpc.ClientConn),
|
||||
extraMetrics: unsafe.Pointer(&map[string]float32{}),
|
||||
deploys: deploys,
|
||||
timestamp: exefi.ModTime().String(),
|
||||
version: string(ver),
|
||||
standalone: standalone,
|
||||
uploadChan: make(chan uploadRequest, 100),
|
||||
siblingProcIndex: make(map[string]uint64),
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
// regularly send status
|
||||
sc := protos.NewMonitorClient(client)
|
||||
hn, _ := os.Hostname()
|
||||
mem := sigar.Mem{}
|
||||
mem.Get()
|
||||
|
||||
metrics := &protos.Metrics{
|
||||
Hostname: hn,
|
||||
Total: bToMb(mem.Total),
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
case <-time.After(5 * time.Second):
|
||||
percent, _ := cpu.Percent(0, false)
|
||||
|
||||
metrics.Cpu = float32(percent[0])
|
||||
metrics.Free = bToMb(mem.ActualFree)
|
||||
metrics.Metrics = *(*map[string]float32)(atomic.LoadPointer(&hc.extraMetrics))
|
||||
|
||||
sc.Report(context.Background(), metrics, grpc.WaitForReady(true))
|
||||
mem.Get()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
exitChan := make(chan *exec.Cmd, 10)
|
||||
operationChan := make(chan *protos.OperationQueryResponse, 10)
|
||||
hc.wg.Add(1)
|
||||
ignoreRecover := int32(0)
|
||||
|
||||
// autorun 처리
|
||||
go func() {
|
||||
defer hc.wg.Done()
|
||||
|
||||
// 메인 operator
|
||||
op := protos.NewOperationClient(hc.client)
|
||||
var op protos.OperationClient
|
||||
myname, _ := os.Executable()
|
||||
myname = path.Base(filepath.ToSlash(myname))
|
||||
if len(path.Ext(myname)) > 0 {
|
||||
myname = myname[:len(myname)-len(path.Ext(myname))]
|
||||
}
|
||||
if myname == "__debug_bin" {
|
||||
myname = "houston"
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
case newClient := <-hc.clientChan:
|
||||
op = protos.NewOperationClient(newClient)
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
|
||||
case exited := <-exitChan:
|
||||
var newprocs []*procmeta
|
||||
for _, proc := range hc.childProcs {
|
||||
if proc.cmd == exited && proc.state != protos.ProcessState_Stopped {
|
||||
proc.state = protos.ProcessState_Stopped
|
||||
if proc.cmd == exited {
|
||||
if proc.isState(protos.ProcessState_Running) || proc.isState(protos.ProcessState_Restart) {
|
||||
go func(proc *procmeta) {
|
||||
if err := proc.cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||
proc.cmd.Process.Signal(os.Kill)
|
||||
}
|
||||
proc.cmd.Wait()
|
||||
proc.cmd.Process.Release()
|
||||
|
||||
if proc.isState(protos.ProcessState_Restart) {
|
||||
if proc.keepLatest {
|
||||
proc.version = "latest"
|
||||
}
|
||||
|
||||
if err := hc.startChildProcess(&shared.StartProcessRequest{
|
||||
Version: proc.version,
|
||||
Name: proc.name,
|
||||
Args: proc.args,
|
||||
}); err != nil {
|
||||
logger.ErrorWithCallStack(err)
|
||||
} else {
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
}
|
||||
}
|
||||
}(proc)
|
||||
}
|
||||
} else {
|
||||
newprocs = append(newprocs, proc)
|
||||
}
|
||||
@ -238,26 +399,66 @@ func NewClient(grpcAddr string, httpAddr string) (HoustonClient, error) {
|
||||
op.Refresh(ctx, hc.makeOperationQueryRequest())
|
||||
|
||||
case resp := <-operationChan:
|
||||
logger.Println("houton query operation :", resp.Operation)
|
||||
|
||||
switch shared.Operation(resp.Operation) {
|
||||
case shared.Deploy:
|
||||
var dr shared.DeployRequest
|
||||
unmarshal(&dr, resp.Args)
|
||||
err := hc.deploy(&dr)
|
||||
if err == nil {
|
||||
prog := gatherDeployedPrograms(dr.Name)
|
||||
logger.Println("args :", dr)
|
||||
|
||||
hn, _ := os.Hostname()
|
||||
|
||||
if err := hc.deploy(&dr, func(dp *protos.DeployingProgress) {
|
||||
dp.Hostname = hn
|
||||
dp.Name = dr.Name
|
||||
dp.Version = dr.Version
|
||||
op.ReportDeployingProgress(ctx, dp)
|
||||
}); err == nil {
|
||||
if dr.Name == "houston" {
|
||||
// houston_update_dir 다운로드가 완료되었으므로 종료
|
||||
// 종료되고나면 스크립트가 알아서 재 실행
|
||||
hc.Shutdown()
|
||||
return
|
||||
}
|
||||
prog := gatherDeployedPrograms(hc.config.StorageRoot, dr.Name)
|
||||
hc.deploys[dr.Name] = prog
|
||||
op.Refresh(ctx, hc.makeOperationQueryRequest())
|
||||
|
||||
op.ReportDeployingProgress(ctx, &protos.DeployingProgress{
|
||||
Hostname: hn,
|
||||
Name: dr.Name,
|
||||
Version: dr.Version,
|
||||
State: "success",
|
||||
Progress: 0,
|
||||
Total: 0,
|
||||
})
|
||||
} else {
|
||||
logger.Println(err)
|
||||
|
||||
op.ReportDeployingProgress(ctx, &protos.DeployingProgress{
|
||||
Hostname: hn,
|
||||
Name: dr.Name,
|
||||
Version: dr.Version,
|
||||
State: "fail:" + err.Error(),
|
||||
Progress: 0,
|
||||
Total: 0,
|
||||
})
|
||||
}
|
||||
|
||||
case shared.Withdraw:
|
||||
var wr shared.WithdrawRequest
|
||||
unmarshal(&wr, resp.Args)
|
||||
logger.Println("args :", wr)
|
||||
|
||||
err := hc.withdraw(&wr)
|
||||
if err == nil {
|
||||
prog := gatherDeployedPrograms(wr.Name)
|
||||
hc.deploys[wr.Name] = prog
|
||||
prog := gatherDeployedPrograms(hc.config.StorageRoot, wr.Name)
|
||||
if len(prog) == 0 {
|
||||
delete(hc.deploys, wr.Name)
|
||||
} else {
|
||||
hc.deploys[wr.Name] = prog
|
||||
}
|
||||
op.Refresh(ctx, hc.makeOperationQueryRequest())
|
||||
} else {
|
||||
logger.Println(err)
|
||||
@ -266,62 +467,99 @@ func NewClient(grpcAddr string, httpAddr string) (HoustonClient, error) {
|
||||
case shared.Start:
|
||||
var sr shared.StartProcessRequest
|
||||
unmarshal(&sr, resp.Args)
|
||||
logger.Println("args :", sr)
|
||||
|
||||
if err := hc.startChildProcess(&sr); err != nil {
|
||||
logger.Println(err)
|
||||
logger.ErrorWithCallStack(err)
|
||||
} else {
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
}
|
||||
|
||||
case shared.Stop:
|
||||
var sr shared.StopProcessRequest
|
||||
unmarshal(&sr, resp.Args)
|
||||
if err := hc.stopChildProcess(&sr); err != nil {
|
||||
logger.Println("args :", sr)
|
||||
|
||||
if err := hc.stopChildProcess(&sr, op); err != nil {
|
||||
logger.Println(err)
|
||||
}
|
||||
|
||||
case shared.Restart:
|
||||
var rr shared.RestartProcessRequest
|
||||
unmarshal(&rr, resp.Args)
|
||||
if err := hc.restartChildProcess(&rr); err != nil {
|
||||
logger.Println("args :", rr)
|
||||
|
||||
if err := hc.restartChildProcess(&rr, op); err != nil {
|
||||
logger.Println(err)
|
||||
}
|
||||
|
||||
case shared.Upload:
|
||||
var ur shared.UploadRequest
|
||||
unmarshal(&ur, resp.Args)
|
||||
if err := hc.uploadFiles(&ur); err != nil {
|
||||
logger.Println(err)
|
||||
case shared.Exception:
|
||||
idstr := resp.Args["id"]
|
||||
id64, _ := strconv.ParseInt(idstr, 10, 0)
|
||||
id := int32(id64)
|
||||
|
||||
var found *procmeta
|
||||
hc.childProcs = gocommon.ShrinkSlice(hc.childProcs, func(e *procmeta) bool {
|
||||
if e.id == id {
|
||||
found = e
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if found != nil {
|
||||
found.cmd.Wait()
|
||||
found.cmd.Process.Release()
|
||||
|
||||
if found.recover && atomic.LoadInt32(&ignoreRecover) == 0 {
|
||||
time.Sleep(time.Second)
|
||||
sr := shared.StartProcessRequest{
|
||||
Name: found.name,
|
||||
Version: found.version,
|
||||
Args: found.args,
|
||||
AutoRestart: found.recover,
|
||||
OutputLogFile: found.logfile,
|
||||
}
|
||||
|
||||
if err := hc.startChildProcess(&sr); err != nil {
|
||||
logger.Println("startChildProcess failed by autorun :", err)
|
||||
logger.ErrorWithCallStack(err)
|
||||
} else {
|
||||
logger.Println("recover success :", sr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if op != nil {
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// receive from stream
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
hc.shutdownFunc = func() {
|
||||
// child process 강제 종료
|
||||
atomic.StoreInt32(&ignoreRecover, 1)
|
||||
|
||||
default:
|
||||
err := hc.checkOperation(operationChan)
|
||||
if err != nil {
|
||||
logger.Println("hc.checkUpdate failed :", err)
|
||||
}
|
||||
for _, procmeta := range hc.childProcs {
|
||||
if procmeta.cmd != nil && procmeta.cmd.Process != nil {
|
||||
procmeta.cmd.Process.Signal(os.Kill)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
hc.shutdownFunc = cancel
|
||||
time.Sleep(time.Second)
|
||||
cancel()
|
||||
}
|
||||
|
||||
hc.exitChan = exitChan
|
||||
hc.ctx = ctx
|
||||
hc.operationChan = operationChan
|
||||
|
||||
return hc, nil
|
||||
}
|
||||
|
||||
func (hc *houstonClient) Shutdown() {
|
||||
hc.shutdownFunc()
|
||||
}
|
||||
|
||||
func (hc *houstonClient) checkOperation(opChan chan<- *protos.OperationQueryResponse) error {
|
||||
func uploadSafe(url, filePath, name, version string) error {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
@ -329,14 +567,189 @@ func (hc *houstonClient) checkOperation(opChan chan<- *protos.OperationQueryResp
|
||||
}
|
||||
}()
|
||||
|
||||
op := protos.NewOperationClient(hc.client)
|
||||
cl, err := op.Query(context.Background(), grpc.WaitForReady(true))
|
||||
t, err := times.Stat(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if file == nil {
|
||||
return errors.New("upload file is missing :" + filePath)
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
// hc.config.HttpAddress+"/upload",
|
||||
httpreq, err := http.NewRequest("POST", url, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hn, _ := os.Hostname()
|
||||
// createTime := file.
|
||||
httpreq.Header.Set("Houston-Service-Name", name)
|
||||
httpreq.Header.Set("Houston-Service-Version", version)
|
||||
httpreq.Header.Set("Houston-Service-Filename", t.BirthTime().UTC().Format(time.DateOnly)+"."+hn+path.Ext(filePath))
|
||||
httpreq.Header.Set("Content-Type", "application/zip")
|
||||
resp, err := http.DefaultClient.Do(httpreq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("upload file failed. response code : %s, %d", filePath, resp.StatusCode)
|
||||
}
|
||||
|
||||
if err := os.Remove(filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hc *houstonClient) Start() {
|
||||
// receive from stream
|
||||
defer func() {
|
||||
hc.wg.Wait()
|
||||
|
||||
for _, proc := range hc.childProcs {
|
||||
if err := proc.cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||
proc.cmd.Process.Signal(os.Kill)
|
||||
proc.setState(protos.ProcessState_Stopping)
|
||||
}
|
||||
}
|
||||
|
||||
for _, proc := range hc.childProcs {
|
||||
proc.cmd.Wait()
|
||||
proc.cmd.Process.Release()
|
||||
}
|
||||
|
||||
close(hc.uploadChan)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// upload 고루틴
|
||||
url := hc.config.HttpAddress + "/upload"
|
||||
for req := range hc.uploadChan {
|
||||
logger.Println("uploadSafe :", req)
|
||||
err := uploadSafe(url, req.logFile, req.name, req.version)
|
||||
if err != nil {
|
||||
logger.Println("uploadSafe return err :", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
|
||||
go func() {
|
||||
c := <-interrupt
|
||||
logger.Println("interrupt!!!!!!!! :", c.String())
|
||||
hc.shutdownFunc()
|
||||
}()
|
||||
|
||||
var client *grpc.ClientConn
|
||||
reconnCount := 0
|
||||
time.Sleep(time.Second)
|
||||
|
||||
if autorun != nil && len(*autorun) > 0 {
|
||||
hascount := strings.Split(*autorun, "/")
|
||||
var service string
|
||||
count := 1
|
||||
if len(hascount) > 1 {
|
||||
service = hascount[0]
|
||||
if len(hascount[1]) > 0 {
|
||||
count, _ = strconv.Atoi(hascount[1])
|
||||
}
|
||||
} else {
|
||||
service = *autorun
|
||||
}
|
||||
|
||||
if cmd, ok := hc.config.Autorun[service]; ok {
|
||||
// service 서비스
|
||||
for i := 0; i < count; i++ {
|
||||
sr := shared.StartProcessRequest{
|
||||
Name: service,
|
||||
Version: cmd.Version,
|
||||
Args: append([]string{cmd.Exec}, cmd.Args...),
|
||||
AutoRestart: cmd.AutoRestart,
|
||||
OutputLogFile: cmd.OutputLogFile,
|
||||
}
|
||||
|
||||
if err := hc.startChildProcess(&sr); err != nil {
|
||||
logger.Println("startChildProcess failed by autorun :", err)
|
||||
logger.ErrorWithCallStack(err)
|
||||
} else {
|
||||
logger.Println("autorun success :", sr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-hc.ctx.Done():
|
||||
return
|
||||
|
||||
default:
|
||||
if client == nil {
|
||||
if reconnCount == 0 {
|
||||
logger.Println("grpc.DialContext :", hc.config.GrpcAddress)
|
||||
}
|
||||
|
||||
reconnCount++
|
||||
|
||||
var err error
|
||||
dialContext, cancelDial := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
client, err = grpc.DialContext(dialContext, hc.config.GrpcAddress, grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
cancelDial()
|
||||
|
||||
if err != nil {
|
||||
logger.Println("grpc.DialContext returns err :", err)
|
||||
} else if client != nil {
|
||||
reconnCount = 0
|
||||
logger.Println("grpc.DialContext succeeded")
|
||||
hc.clientChan <- client
|
||||
}
|
||||
}
|
||||
|
||||
if client != nil {
|
||||
err := hc.checkOperation(client)
|
||||
if err != nil {
|
||||
if status.Convert(err).Message() != status.Convert(context.Canceled).Message() {
|
||||
logger.Println("grpc.DialContext hc.checkOperation failed :", err)
|
||||
}
|
||||
client = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (hc *houstonClient) Shutdown() {
|
||||
hc.shutdownFunc()
|
||||
}
|
||||
|
||||
func (hc *houstonClient) checkOperation(client *grpc.ClientConn) error {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
logger.Println(r)
|
||||
}
|
||||
}()
|
||||
|
||||
op := protos.NewOperationClient(client)
|
||||
cl, err := op.Query(hc.ctx, grpc.WaitForReady(true))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cl.Send(hc.makeOperationQueryRequest())
|
||||
|
||||
if err != nil {
|
||||
cl.CloseSend()
|
||||
return err
|
||||
@ -348,10 +761,6 @@ func (hc *houstonClient) checkOperation(opChan chan<- *protos.OperationQueryResp
|
||||
cl.CloseSend()
|
||||
return err
|
||||
}
|
||||
opChan <- update
|
||||
hc.operationChan <- update
|
||||
}
|
||||
}
|
||||
|
||||
func (hc *houstonClient) SetReportMetrics(extra map[string]float32) {
|
||||
atomic.StorePointer(&hc.extraMetrics, unsafe.Pointer(&extra))
|
||||
}
|
||||
|
||||
26
client/client_linux.go
Normal file
26
client/client_linux.go
Normal file
@ -0,0 +1,26 @@
|
||||
//go:build linux
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
)
|
||||
|
||||
func set_affinity(pid int, cpu int) {
|
||||
var cpuset unix.CPUSet
|
||||
err := unix.SchedGetaffinity(pid, &cpuset)
|
||||
if err != nil {
|
||||
logger.Println("SchedGetaffinity failed :", err)
|
||||
}
|
||||
|
||||
count := cpuset.Count()
|
||||
cpuset.Zero()
|
||||
cpuset.Set(cpu % count)
|
||||
|
||||
err = unix.SchedSetaffinity(pid, &cpuset)
|
||||
if err != nil {
|
||||
logger.Println("SchedSetaffinity failed :", err)
|
||||
}
|
||||
}
|
||||
41
client/client_misc.go
Normal file
41
client/client_misc.go
Normal file
@ -0,0 +1,41 @@
|
||||
//go:build !linux
|
||||
|
||||
package client
|
||||
|
||||
func set_affinity(pid int, cpu int) {
|
||||
|
||||
}
|
||||
|
||||
// package main
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "syscall"
|
||||
// "time"
|
||||
// "unsafe"
|
||||
// )
|
||||
|
||||
// func main() {
|
||||
// var mask uintptr
|
||||
|
||||
// // Get the current CPU affinity of the process
|
||||
// if _, _, err := syscall.RawSyscall(syscall.SYS_SCHED_GETAFFINITY, 0, uintptr(unsafe.Sizeof(mask)), uintptr(unsafe.Pointer(&mask))); err != 0 {
|
||||
// fmt.Println("Failed to get CPU affinity:", err)
|
||||
// return
|
||||
// }
|
||||
// fmt.Println("Current CPU affinity:", mask)
|
||||
|
||||
// // Set the new CPU affinity
|
||||
// mask = 3
|
||||
// if _, _, err := syscall.RawSyscall(syscall.SYS_SCHED_SETAFFINITY, 0, uintptr(unsafe.Sizeof(mask)), uintptr(unsafe.Pointer(&mask))); err != 0 {
|
||||
// fmt.Println("Failed to set CPU affinity:", err)
|
||||
// return
|
||||
// }
|
||||
// fmt.Println("New CPU affinity:", mask)
|
||||
|
||||
// // some code
|
||||
// for {
|
||||
// println("Hello, World!")
|
||||
// time.Sleep(1 * time.Second)
|
||||
// }
|
||||
// }
|
||||
35
client/client_test.go
Normal file
35
client/client_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_houstonClient_Start(t *testing.T) {
|
||||
tc := make(chan int, 1000)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
// receive
|
||||
defer wg.Done()
|
||||
|
||||
for v := range tc {
|
||||
fmt.Println(v)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// send
|
||||
for i := 0; i < 100; i++ {
|
||||
tc <- i
|
||||
}
|
||||
close(tc)
|
||||
fmt.Println("channel close called")
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
222
client/deploy.go
222
client/deploy.go
@ -3,18 +3,20 @@ package client
|
||||
import (
|
||||
"archive/tar"
|
||||
"archive/zip"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"repositories.action2quare.com/ayo/go-ayo/logger"
|
||||
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
"repositories.action2quare.com/ayo/houston/shared"
|
||||
"repositories.action2quare.com/ayo/houston/shared/protos"
|
||||
|
||||
@ -23,17 +25,46 @@ import (
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func download(dir string, urlpath string, accessToken string) (string, error) {
|
||||
const (
|
||||
houston_update_dir = "./houston.update"
|
||||
)
|
||||
|
||||
func pof2(x int64, min int64) (out int64) {
|
||||
out = 1
|
||||
org := x
|
||||
for (x >> 1) > 0 {
|
||||
out = out << 1
|
||||
x = x >> 1
|
||||
}
|
||||
if org > out {
|
||||
out = out << 1
|
||||
}
|
||||
|
||||
if out < min {
|
||||
out = min
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func download(dir string, urlpath string, accessToken string, cb func(int64, int64)) (target string, err error) {
|
||||
logger.Println("start downloading", dir, urlpath)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
logger.Println("downloading failed :", err)
|
||||
} else {
|
||||
logger.Println("downloading succeeded")
|
||||
}
|
||||
}()
|
||||
|
||||
parsed, err := url.Parse(urlpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
req, _ := http.NewRequest("GET", urlpath, nil)
|
||||
if len(accessToken) > 0 {
|
||||
req.Header.Add("Authorization", accessToken)
|
||||
}
|
||||
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.51")
|
||||
req.Header.Add("As-X-UrlHash", accessToken)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -44,18 +75,36 @@ func download(dir string, urlpath string, accessToken string) (string, error) {
|
||||
return "", fmt.Errorf("download failed : %d %s", resp.StatusCode, parsed.Path)
|
||||
}
|
||||
|
||||
out, err := os.Create(path.Join(dir, path.Base(parsed.Path)))
|
||||
out, err := os.Create(path.Join(dir, path.Base(filepath.ToSlash(parsed.Path))))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
cl := resp.Header.Get("Content-Length")
|
||||
totalLength, _ := strconv.ParseInt(cl, 10, 0)
|
||||
totalWritten := int64(0)
|
||||
chunkSize := pof2(totalLength/100, 1024*1024)
|
||||
if cb != nil {
|
||||
cb(0, totalLength)
|
||||
}
|
||||
|
||||
return out.Name(), nil
|
||||
for {
|
||||
written, err := io.CopyN(out, resp.Body, chunkSize)
|
||||
totalWritten += written
|
||||
if cb != nil {
|
||||
cb(totalWritten, totalLength)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return filepath.ToSlash(out.Name()), nil
|
||||
}
|
||||
|
||||
func unzip(fname string) error {
|
||||
@ -64,7 +113,10 @@ func unzip(fname string) error {
|
||||
os.Remove(fname)
|
||||
return err
|
||||
}
|
||||
defer archive.Close()
|
||||
defer func() {
|
||||
archive.Close()
|
||||
os.Remove(fname)
|
||||
}()
|
||||
|
||||
verpath := path.Dir(fname)
|
||||
for _, f := range archive.File {
|
||||
@ -75,14 +127,16 @@ func unzip(fname string) error {
|
||||
name = f.Name
|
||||
}
|
||||
|
||||
name = strings.ReplaceAll(name, `\`, "/")
|
||||
filePath := path.Join(verpath, name)
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(filePath, os.ModePerm)
|
||||
if f.FileInfo().IsDir() || strings.HasSuffix(f.FileInfo().Name(), `\`) {
|
||||
if err = os.MkdirAll(filePath, 0775); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(path.Dir(filePath), os.ModePerm); err != nil {
|
||||
if err := os.MkdirAll(path.Dir(filePath), 0775); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -103,6 +157,7 @@ func unzip(fname string) error {
|
||||
dstFile.Close()
|
||||
fileInArchive.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -111,7 +166,10 @@ func untar(fname string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
defer func() {
|
||||
file.Close()
|
||||
os.Remove(fname)
|
||||
}()
|
||||
|
||||
verpath := path.Dir(fname)
|
||||
tarReader := tar.NewReader(file)
|
||||
@ -126,7 +184,7 @@ func untar(fname string) error {
|
||||
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
if err := os.MkdirAll(path.Join(verpath, header.Name), 0755); err != nil {
|
||||
if err := os.MkdirAll(path.Join(verpath, header.Name), 0775); err != nil {
|
||||
return err
|
||||
}
|
||||
case tar.TypeReg:
|
||||
@ -143,6 +201,7 @@ func untar(fname string) error {
|
||||
return errors.New("unknown type")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -150,8 +209,9 @@ func (hc *houstonClient) prepareDeploy(name string, version string) (destPath st
|
||||
// houston관리용임을 표시하기 위해 더미파일 생성
|
||||
defer func() {
|
||||
var flagf *os.File
|
||||
if _, err := os.Stat(path.Join(name, "@houston")); os.IsNotExist(err) {
|
||||
flagf, err = os.Create(path.Join(name, "@houston"))
|
||||
markerPath := path.Join(hc.config.StorageRoot, name, "@houston")
|
||||
if _, err := os.Stat(markerPath); os.IsNotExist(err) {
|
||||
flagf, err = os.Create(markerPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -160,14 +220,8 @@ func (hc *houstonClient) prepareDeploy(name string, version string) (destPath st
|
||||
}
|
||||
}()
|
||||
|
||||
verpath := path.Join("./", name, version)
|
||||
if _, err := os.Stat(verpath); os.IsNotExist(err) {
|
||||
// 없네? 만들면 된다.
|
||||
err = os.MkdirAll(verpath, fs.FileMode(os.O_WRONLY))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
verpath := path.Join(hc.config.StorageRoot, name, version)
|
||||
if _, err := os.Stat(verpath); !os.IsNotExist(err) {
|
||||
// 있네? 재배포 가능한가?
|
||||
for _, child := range hc.childProcs {
|
||||
if child.version == version && child.name == name {
|
||||
@ -180,25 +234,97 @@ func (hc *houstonClient) prepareDeploy(name string, version string) (destPath st
|
||||
return verpath, nil
|
||||
}
|
||||
|
||||
func (hc *houstonClient) deploy(req *shared.DeployRequest) error {
|
||||
func (hc *houstonClient) makeDownloadUrl(rel string) string {
|
||||
out := rel
|
||||
if !strings.HasPrefix(out, "http") {
|
||||
tks := strings.SplitN(hc.config.HttpAddress, "://", 2)
|
||||
out = fmt.Sprintf("%s://%s", tks[0], path.Join(tks[1], rel))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func copyfile(src, dst string) error {
|
||||
fi, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
inmode := fi.Mode()
|
||||
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
copied, err := io.Copy(out, in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if copied < fi.Size() {
|
||||
return errors.New("copy not completed")
|
||||
}
|
||||
if err := out.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := out.Chmod(inmode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hc *houstonClient) deploy(req *shared.DeployRequest, cb func(*protos.DeployingProgress)) (err error) {
|
||||
logger.Println("start deploying")
|
||||
root, err := hc.prepareDeploy(req.Name, req.Version)
|
||||
|
||||
var root string
|
||||
if req.Name == "houston" {
|
||||
// houston은 버전없이 houston_update_dir폴더로 다운로드
|
||||
root = houston_update_dir
|
||||
// 이미 houston_update_dir가 있을 수도 있으므로 폴더채로 삭제
|
||||
os.RemoveAll(houston_update_dir)
|
||||
} else {
|
||||
root, err = hc.prepareDeploy(req.Name, req.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = os.MkdirAll(root, 0775)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(req.Url, "http") {
|
||||
tks := strings.SplitN(hc.httpAddr, "://", 2)
|
||||
req.Url = fmt.Sprintf("%s://%s", tks[0], path.Join(tks[1], req.Url))
|
||||
}
|
||||
|
||||
logger.Println("start downloading", req.Url)
|
||||
// verpath에 배포 시작
|
||||
fname, err := download(root, req.Url, req.AccessToken)
|
||||
h := md5.New()
|
||||
h.Write([]byte(strings.Trim(req.Url, "/")))
|
||||
at := hex.EncodeToString(h.Sum(nil))
|
||||
var fname string
|
||||
fname, err = download(root, hc.makeDownloadUrl(req.Url), at, func(written int64, total int64) {
|
||||
prog := protos.DeployingProgress{
|
||||
State: "download",
|
||||
Progress: written,
|
||||
Total: total,
|
||||
}
|
||||
cb(&prog)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cb(&protos.DeployingProgress{
|
||||
State: "unpack",
|
||||
Progress: 0,
|
||||
Total: 0,
|
||||
})
|
||||
|
||||
switch path.Ext(fname) {
|
||||
case ".zip":
|
||||
err = unzip(fname)
|
||||
@ -206,23 +332,31 @@ func (hc *houstonClient) deploy(req *shared.DeployRequest) error {
|
||||
err = untar(fname)
|
||||
}
|
||||
|
||||
if err == nil && len(req.Config) > 0 && req.Name != "houston" {
|
||||
// config.json도 다운로드
|
||||
h := md5.New()
|
||||
h.Write([]byte(strings.Trim(req.Config, "/")))
|
||||
at = hex.EncodeToString(h.Sum(nil))
|
||||
|
||||
_, err = download(root, hc.makeDownloadUrl(req.Config), at, nil)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (hc *houstonClient) withdraw(req *shared.WithdrawRequest) error {
|
||||
fd, _ := os.Stat(path.Join("./", req.Name, req.Version))
|
||||
targetPath := path.Join(hc.config.StorageRoot, req.Name, req.Version)
|
||||
fd, _ := os.Stat(targetPath)
|
||||
if fd != nil {
|
||||
if fd.IsDir() {
|
||||
for _, running := range hc.childProcs {
|
||||
if running.name == req.Name && running.version == req.Version {
|
||||
if running.name == req.Name && (len(req.Version) == 0 || running.version == req.Version) {
|
||||
// 회수하려는 버전이 돌고 있다
|
||||
if running.state != protos.ProcessState_Stopped {
|
||||
return fmt.Errorf("withdraw failed. %s@%s is still running", req.Name, req.Version)
|
||||
}
|
||||
return fmt.Errorf("withdraw failed. %s@%s is still running", req.Name, req.Version)
|
||||
}
|
||||
}
|
||||
|
||||
return os.RemoveAll(path.Join("./", req.Name, req.Version))
|
||||
return os.RemoveAll(targetPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
9
client/deploy_test.go
Normal file
9
client/deploy_test.go
Normal file
@ -0,0 +1,9 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDownload(t *testing.T) {
|
||||
|
||||
}
|
||||
133
client/node_exporter.go
Normal file
133
client/node_exporter.go
Normal file
@ -0,0 +1,133 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stdlog "log"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"sort"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
promcollectors "github.com/prometheus/client_golang/prometheus/collectors"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/prometheus/common/version"
|
||||
"github.com/prometheus/node_exporter/collector"
|
||||
)
|
||||
|
||||
// handler wraps an unfiltered http.Handler but uses a filtered handler,
|
||||
// created on the fly, if filtering is requested. Create instances with
|
||||
// newHandler.
|
||||
type handler struct {
|
||||
unfilteredHandler http.Handler
|
||||
// exporterMetricsRegistry is a separate registry for the metrics about
|
||||
// the exporter itself.
|
||||
exporterMetricsRegistry *prometheus.Registry
|
||||
includeExporterMetrics bool
|
||||
maxRequests int
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
func NewHandlerForNodeExporter(includeExporterMetrics bool, maxRequests int, logger log.Logger) *handler {
|
||||
h := &handler{
|
||||
exporterMetricsRegistry: prometheus.NewRegistry(),
|
||||
includeExporterMetrics: includeExporterMetrics,
|
||||
maxRequests: maxRequests,
|
||||
logger: logger,
|
||||
}
|
||||
if h.includeExporterMetrics {
|
||||
h.exporterMetricsRegistry.MustRegister(
|
||||
promcollectors.NewProcessCollector(promcollectors.ProcessCollectorOpts{}),
|
||||
promcollectors.NewGoCollector(),
|
||||
)
|
||||
}
|
||||
if innerHandler, err := h.innerHandler(); err != nil {
|
||||
panic(fmt.Sprintf("Couldn't create metrics handler: %s", err))
|
||||
} else {
|
||||
h.unfilteredHandler = innerHandler
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler.
|
||||
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
filters := r.URL.Query()["collect[]"]
|
||||
level.Debug(h.logger).Log("msg", "collect query:", "filters", filters)
|
||||
|
||||
if len(filters) == 0 {
|
||||
// No filters, use the prepared unfiltered handler.
|
||||
h.unfilteredHandler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
// To serve filtered metrics, we create a filtering handler on the fly.
|
||||
filteredHandler, err := h.innerHandler(filters...)
|
||||
if err != nil {
|
||||
level.Warn(h.logger).Log("msg", "Couldn't create filtered metrics handler:", "err", err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err)))
|
||||
return
|
||||
}
|
||||
filteredHandler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// innerHandler is used to create both the one unfiltered http.Handler to be
|
||||
// wrapped by the outer handler and also the filtered handlers created on the
|
||||
// fly. The former is accomplished by calling innerHandler without any arguments
|
||||
// (in which case it will log all the collectors enabled via command-line
|
||||
// flags).
|
||||
func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
|
||||
nc, err := collector.NewNodeCollector(h.logger, filters...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't create collector: %s", err)
|
||||
}
|
||||
|
||||
// Only log the creation of an unfiltered handler, which should happen
|
||||
// only once upon startup.
|
||||
if len(filters) == 0 {
|
||||
level.Info(h.logger).Log("msg", "Enabled collectors")
|
||||
collectors := []string{}
|
||||
for n := range nc.Collectors {
|
||||
collectors = append(collectors, n)
|
||||
}
|
||||
sort.Strings(collectors)
|
||||
for _, c := range collectors {
|
||||
level.Info(h.logger).Log("collector", c)
|
||||
}
|
||||
}
|
||||
|
||||
r := prometheus.NewRegistry()
|
||||
r.MustRegister(version.NewCollector("node_exporter"))
|
||||
if err := r.Register(nc); err != nil {
|
||||
return nil, fmt.Errorf("couldn't register node collector: %s", err)
|
||||
}
|
||||
|
||||
var handler http.Handler
|
||||
if h.includeExporterMetrics {
|
||||
handler = promhttp.HandlerFor(
|
||||
prometheus.Gatherers{h.exporterMetricsRegistry, r},
|
||||
promhttp.HandlerOpts{
|
||||
ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(h.logger)), "", 0),
|
||||
ErrorHandling: promhttp.ContinueOnError,
|
||||
MaxRequestsInFlight: h.maxRequests,
|
||||
Registry: h.exporterMetricsRegistry,
|
||||
},
|
||||
)
|
||||
// Note that we have to use h.exporterMetricsRegistry here to
|
||||
// use the same promhttp metrics for all expositions.
|
||||
handler = promhttp.InstrumentMetricHandler(
|
||||
h.exporterMetricsRegistry, handler,
|
||||
)
|
||||
} else {
|
||||
handler = promhttp.HandlerFor(
|
||||
r,
|
||||
promhttp.HandlerOpts{
|
||||
ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(h.logger)), "", 0),
|
||||
ErrorHandling: promhttp.ContinueOnError,
|
||||
MaxRequestsInFlight: h.maxRequests,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return handler, nil
|
||||
}
|
||||
@ -2,23 +2,26 @@ package client
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime/debug"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"repositories.action2quare.com/ayo/go-ayo/logger"
|
||||
|
||||
"github.com/Knetic/govaluate"
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
"repositories.action2quare.com/ayo/gocommon/metric"
|
||||
"repositories.action2quare.com/ayo/houston/shared"
|
||||
"repositories.action2quare.com/ayo/houston/shared/protos"
|
||||
)
|
||||
@ -39,22 +42,43 @@ func lastExecutionArgs(verpath string) []string {
|
||||
return out
|
||||
}
|
||||
|
||||
func (meta *procmeta) zipLogFiles(req *shared.UploadRequest, start, except string) (string, []string, error) {
|
||||
root := path.Join(req.Name, req.Version)
|
||||
matches, err := filepath.Glob(path.Join(root, req.Filter))
|
||||
func (hc *houstonClient) uploadToAppendLog(logFile string, name string, version string) {
|
||||
hc.uploadChan <- uploadRequest{
|
||||
logFile: logFile,
|
||||
name: name,
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
|
||||
func findMatchFiles(storageRoot, name, version, filter string) (string, []string) {
|
||||
root := path.Join(storageRoot, name, version)
|
||||
matches, err := filepath.Glob(path.Join(root, filter))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if len(matches) == 0 {
|
||||
return "", nil, nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
root = path.Join(root, path.Dir(req.Filter))
|
||||
// Create a file to write the archive to.
|
||||
f, err := os.CreateTemp("", "")
|
||||
root = path.Join(root, path.Dir(filter))
|
||||
out := make([]string, 0, len(matches))
|
||||
for _, file := range matches {
|
||||
file = filepath.ToSlash(file)
|
||||
if file == root {
|
||||
continue
|
||||
}
|
||||
|
||||
out = append(out, file)
|
||||
}
|
||||
slices.Sort(out)
|
||||
return root, out
|
||||
}
|
||||
|
||||
func zipCompressFiles(root string, matches []string) (string, error) {
|
||||
f, err := os.CreateTemp(os.TempDir(), "*.zip")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
@ -63,91 +87,169 @@ func (meta *procmeta) zipLogFiles(req *shared.UploadRequest, start, except strin
|
||||
|
||||
oldestFile := ""
|
||||
for i, file := range matches {
|
||||
file = filepath.ToSlash(file)
|
||||
matches[i] = file
|
||||
if file == root {
|
||||
continue
|
||||
}
|
||||
if file >= except {
|
||||
break
|
||||
}
|
||||
if len(start) > 0 && file < start {
|
||||
continue
|
||||
if fi, err := os.Lstat(file); err == nil {
|
||||
if (fi.Mode() & os.ModeSymlink) == os.ModeSymlink {
|
||||
matches[i] = ""
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(oldestFile) == 0 {
|
||||
oldestFile = path.Base(file)
|
||||
oldestFile = path.Base(filepath.ToSlash(file))
|
||||
}
|
||||
|
||||
relative := file[len(root)+1:]
|
||||
fw, err := w.Create(relative)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
return "", nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
src, err := os.Open(file)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
return "", nil, err
|
||||
return "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
if _, err = io.Copy(fw, src); err != nil {
|
||||
logger.Error(err)
|
||||
return "", nil, err
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return f.Name(), matches, nil
|
||||
// defer func() {
|
||||
// tempname := f.Name()
|
||||
// f.Close()
|
||||
|
||||
// resp, _ := http.Post(req.Url, "application/zip", f)
|
||||
// if resp != nil && resp.Body != nil {
|
||||
// resp.Body.Close()
|
||||
// }
|
||||
// os.Remove(tempname)
|
||||
// if del, err := strconv.ParseBool(req.DeleteAfterUploaded); del && err == nil {
|
||||
// for _, file := range matches {
|
||||
// if strings.HasSuffix(file, except) {
|
||||
// continue
|
||||
// }
|
||||
// os.Remove(file)
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
|
||||
// Create a new zip archive.
|
||||
|
||||
//}(f)
|
||||
|
||||
//return nil
|
||||
return f.Name(), nil
|
||||
}
|
||||
|
||||
func prepareProcessLaunch(req *shared.StartProcessRequest) *procmeta {
|
||||
re := regexp.MustCompile(`[^\s"']+|"([^"]*)"|'([^']*)`)
|
||||
args := re.FindAllString(req.Args, -1)
|
||||
func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) (*procmeta, error) {
|
||||
if len(req.Args) == 0 {
|
||||
return nil, errors.New("args is empty")
|
||||
}
|
||||
|
||||
verpath := path.Join("./", req.Name, req.Version)
|
||||
foundVersion := req.Version
|
||||
if req.Version == "latest" {
|
||||
entries, err := os.ReadDir(path.Join(storageRoot, req.Name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var latestTimestamp time.Time
|
||||
var latestVersion string
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
fi, err := entry.Info()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
createTime := fi.ModTime()
|
||||
if latestTimestamp.Before(createTime) {
|
||||
latestTimestamp = fi.ModTime()
|
||||
latestVersion = fi.Name()
|
||||
}
|
||||
}
|
||||
|
||||
if len(latestVersion) > 0 {
|
||||
foundVersion = latestVersion
|
||||
}
|
||||
}
|
||||
|
||||
verpath := path.Join(storageRoot, req.Name, foundVersion)
|
||||
fi, err := os.Stat(verpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
exefile := "./" + path.Clean(strings.TrimPrefix(req.Args[0], "/"))
|
||||
os.Chmod(path.Join(verpath, exefile), 0777)
|
||||
|
||||
exef, _ := os.Executable()
|
||||
expanded := make([]string, len(req.Args))
|
||||
for i, arg := range req.Args {
|
||||
expanded[i] = os.ExpandEnv(arg)
|
||||
}
|
||||
|
||||
exename := path.Join(path.Dir(strings.ReplaceAll(exef, "\\", "/")), verpath, exefile)
|
||||
|
||||
logger.Println("exefile :", exefile)
|
||||
logger.Println("verpath :", verpath)
|
||||
logger.Println("exef :", exef)
|
||||
logger.Println("path.Dir :", path.Dir(exef))
|
||||
logger.Println("exename :", exename)
|
||||
|
||||
cmd := exec.Command(os.ExpandEnv(exename), expanded[1:]...)
|
||||
|
||||
if err == nil && fi.IsDir() {
|
||||
cmd := exec.Command("./"+args[0], args[1:]...)
|
||||
cmd.Dir = verpath
|
||||
stdin, _ := cmd.StdinPipe()
|
||||
|
||||
seq++
|
||||
return &procmeta{
|
||||
cmd: cmd,
|
||||
name: req.Name,
|
||||
version: req.Version,
|
||||
state: protos.ProcessState_Stopped,
|
||||
stdin: stdin,
|
||||
logUploadChan: make(chan *shared.UploadRequest),
|
||||
buffers: bufferStack{cursor: 0},
|
||||
id: seq,
|
||||
cmd: cmd,
|
||||
name: req.Name,
|
||||
args: req.Args,
|
||||
version: foundVersion,
|
||||
recover: req.AutoRestart,
|
||||
verpath: verpath,
|
||||
state: int32(protos.ProcessState_Stopped),
|
||||
stdin: stdin,
|
||||
logfile: req.OutputLogFile,
|
||||
keepLatest: req.Version == "latest",
|
||||
}, nil
|
||||
}
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
|
||||
func evaluateArgs(args []string, params map[string]any) ([]string, error) {
|
||||
re := regexp.MustCompile(`\$\(\((.*?)\)\)`)
|
||||
|
||||
for i, input := range args {
|
||||
matches := re.FindAllStringSubmatch(input, -1)
|
||||
if len(matches) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, match := range matches {
|
||||
if len(match) > 1 {
|
||||
expression := strings.TrimSpace(match[1])
|
||||
expr, err := govaluate.NewEvaluableExpression(expression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := expr.Evaluate(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 원래 표현식을 결과로 대체
|
||||
input = strings.Replace(input, match[0], fmt.Sprintf("%v", result), -1)
|
||||
}
|
||||
}
|
||||
|
||||
args[i] = input
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func parseEnv(input []string) map[string]any {
|
||||
output := make(map[string]any, len(input))
|
||||
for _, envkv := range input {
|
||||
kv := strings.SplitN(envkv, "=", 2)
|
||||
parsed, err := strconv.ParseInt(kv[1], 10, 0)
|
||||
if err == nil {
|
||||
output[kv[0]] = parsed
|
||||
} else {
|
||||
parsed, err := strconv.ParseFloat(kv[1], 32)
|
||||
if err == nil {
|
||||
output[kv[0]] = parsed
|
||||
} else {
|
||||
output[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return output
|
||||
}
|
||||
|
||||
func (hc *houstonClient) launch(meta *procmeta) error {
|
||||
@ -160,310 +262,286 @@ func (hc *houstonClient) launch(meta *procmeta) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(path.Join(meta.cmd.Dir, "logs"), os.ModePerm)
|
||||
logfolder := path.Join(meta.verpath, "logs")
|
||||
err = os.MkdirAll(logfolder, 0775)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relayChan := make(chan struct {
|
||||
size int
|
||||
buf []byte
|
||||
})
|
||||
logUploader := func(localctx context.Context, logfilePath string, logChan chan []byte) {
|
||||
var logFile *os.File
|
||||
var logFilePath string
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
logger.Println(r)
|
||||
debug.PrintStack()
|
||||
ext := path.Ext(logfilePath)
|
||||
head := logfilePath[:len(logfilePath)-len(ext)]
|
||||
if len(head) > 0 && !strings.HasSuffix(head, "/") {
|
||||
head += "."
|
||||
}
|
||||
|
||||
writeLog := func(log []byte) {
|
||||
if logFile == nil {
|
||||
logFilePath = head + time.Now().UTC().Format("2006-01-02.150405") + ext
|
||||
logFile, _ = os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
|
||||
}
|
||||
for written := 0; written < len(log); {
|
||||
n, err := logFile.Write(log[written:])
|
||||
if err != nil {
|
||||
logger.Println("write log file failed :", logfilePath, err)
|
||||
break
|
||||
} else {
|
||||
written += n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if logFile != nil {
|
||||
logFile.Close()
|
||||
logFile = nil
|
||||
hc.uploadToAppendLog(logFilePath, meta.name, meta.version)
|
||||
}
|
||||
close(relayChan)
|
||||
hc.exitChan <- meta.cmd
|
||||
}()
|
||||
|
||||
now := time.Now().UTC()
|
||||
ext := path.Ext(meta.cmd.Args[0])
|
||||
nameonly := path.Base(meta.cmd.Args[0])
|
||||
if len(ext) > 0 {
|
||||
nameonly = nameonly[:len(nameonly)-len(ext)]
|
||||
}
|
||||
ts := now.Format("2006-01-02T15-04-05")
|
||||
stdPrefix := path.Join(meta.cmd.Dir, "logs", fmt.Sprintf("%s_%s", nameonly, ts))
|
||||
logfile, _ := os.Create(stdPrefix + "_0.log")
|
||||
defer logfile.Close()
|
||||
defer func() {
|
||||
for {
|
||||
select {
|
||||
case log := <-logChan:
|
||||
writeLog(log)
|
||||
|
||||
logfileIdx := 0
|
||||
for {
|
||||
thisFileSize := 0
|
||||
switchToNextFile := func() string {
|
||||
logfileIdx++
|
||||
nextFile := fmt.Sprintf("%s_%d.log", stdPrefix, logfileIdx)
|
||||
if nextLogfile, err := os.Create(nextFile); err == nil {
|
||||
logfile.Close()
|
||||
logfile = nextLogfile
|
||||
}
|
||||
thisFileSize = 0
|
||||
return nextFile
|
||||
}
|
||||
|
||||
uploadStartFile := ""
|
||||
select {
|
||||
case req := <-meta.logUploadChan:
|
||||
nextFile := switchToNextFile()
|
||||
startFile := uploadStartFile
|
||||
uploadStartFile = nextFile
|
||||
go func(startFile, nextFile string) {
|
||||
zipFile, srcFiles, err := meta.zipLogFiles(req, startFile, nextFile)
|
||||
if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 {
|
||||
zf, _ := os.Open(zipFile)
|
||||
if zf != nil {
|
||||
req, err := http.NewRequest("POST", hc.httpAddr+"/upload", zf)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
req.Header.Set("Houston-Service-Name", meta.name)
|
||||
req.Header.Set("Houston-Service-Version", meta.version)
|
||||
req.Header.Set("Houston-Service-Filename", path.Base(srcFiles[0])+".zip")
|
||||
req.Header.Set("Content-Type", "application/zip")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
for _, oldf := range srcFiles {
|
||||
os.Remove(oldf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}(startFile, nextFile)
|
||||
|
||||
case bt := <-relayChan:
|
||||
if bt.buf == nil {
|
||||
default:
|
||||
// logChan에 있는 모든 로그 소비
|
||||
return
|
||||
}
|
||||
logfile.Write(bt.buf[:bt.size])
|
||||
meta.buffers.push(bt.buf)
|
||||
thisFileSize += bt.size
|
||||
if thisFileSize > 1024*1024 {
|
||||
switchToNextFile()
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
heartbeat := time.After(time.Minute)
|
||||
select {
|
||||
case <-localctx.Done():
|
||||
return
|
||||
|
||||
case <-heartbeat:
|
||||
heartbeat = time.After(time.Minute)
|
||||
// 지금까지의 로그를 저장해서 업로드
|
||||
if logFile != nil {
|
||||
logFile.Close()
|
||||
logFile = nil
|
||||
hc.uploadToAppendLog(logFilePath, meta.name, meta.version)
|
||||
}
|
||||
|
||||
case log := <-logChan:
|
||||
writeLog(log)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stdReader := func(r io.ReadCloser, logfilePath string, verify func(buff []byte) bool) {
|
||||
defer func() {
|
||||
reco := recover()
|
||||
if reco != nil {
|
||||
logger.Println(reco)
|
||||
}
|
||||
r.Close()
|
||||
}()
|
||||
|
||||
localctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
logChan := make(chan []byte, 1)
|
||||
go logUploader(localctx, logfilePath, logChan)
|
||||
|
||||
reader := bufio.NewReader(r)
|
||||
for {
|
||||
buff, err := reader.ReadBytes('\n')
|
||||
if err != nil {
|
||||
logger.Println("ReadBytes at stdReader return err :", err, meta.name)
|
||||
break
|
||||
}
|
||||
|
||||
if verify(buff) {
|
||||
if len(buff) > 0 {
|
||||
logChan <- buff
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var evalfile string
|
||||
if len(meta.logfile) > 0 {
|
||||
evalfile = path.Join(logfolder, meta.logfile)
|
||||
} else {
|
||||
evalfile = logfolder + "/"
|
||||
}
|
||||
|
||||
go func() {
|
||||
metricExporter := metric.NewPrometheusExport(hc.config.MetricNamespace)
|
||||
defer metricExporter.Shutdown()
|
||||
|
||||
var metricBuffer []byte
|
||||
readingMetric := false
|
||||
stdReader(stdout, evalfile+".log", func(buff []byte) bool {
|
||||
if readingMetric {
|
||||
metricBuffer = append(metricBuffer, buff...)
|
||||
} else if buff[0] == metric.METRIC_HEAD_INLINE {
|
||||
readingMetric = true
|
||||
metricBuffer = append(metricBuffer, buff[1:]...)
|
||||
}
|
||||
|
||||
if readingMetric {
|
||||
if metricBuffer[len(metricBuffer)-2] == metric.METRIC_TAIL_INLINE {
|
||||
readingMetric = false
|
||||
|
||||
metricBuffer = metricBuffer[:len(metricBuffer)-2]
|
||||
if metricBuffer[0] == '{' {
|
||||
var desc metric.MetricDescription
|
||||
if err := json.Unmarshal(metricBuffer, &desc); err != nil {
|
||||
logger.Println("unmarshal metric failed :", err, string(metricBuffer))
|
||||
return false
|
||||
}
|
||||
|
||||
if desc.ConstLabels == nil {
|
||||
desc.ConstLabels = make(map[string]string)
|
||||
}
|
||||
|
||||
for k, v := range hc.config.ConstLabels {
|
||||
desc.ConstLabels[k] = v
|
||||
}
|
||||
|
||||
desc.ConstLabels["job"] = meta.name
|
||||
metricExporter.RegisterMetric(&desc)
|
||||
} else {
|
||||
key, val := metric.ReadMetricValue(metricBuffer)
|
||||
metricExporter.UpdateMetric(key, val)
|
||||
}
|
||||
|
||||
metricBuffer = metricBuffer[:0]
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
logger.Println("stdReader is terminated :", meta.name)
|
||||
|
||||
if meta.isState(protos.ProcessState_Running) {
|
||||
// state는 running인데 종료됐으면 exception처리
|
||||
hc.operationChan <- &protos.OperationQueryResponse{
|
||||
Operation: string(shared.Exception),
|
||||
Args: map[string]string{
|
||||
"id": fmt.Sprintf("%d", meta.id),
|
||||
},
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
stdReader := func(r io.Reader) {
|
||||
defer func() {
|
||||
recover()
|
||||
stdout.Close()
|
||||
}()
|
||||
go stdReader(stderr, evalfile+".err", func([]byte) bool { return true })
|
||||
|
||||
for {
|
||||
buff := meta.buffers.pop()
|
||||
size, err := r.Read(buff)
|
||||
if err != nil {
|
||||
relayChan <- struct {
|
||||
size int
|
||||
buf []byte
|
||||
}{buf: nil}
|
||||
break
|
||||
}
|
||||
if size > 0 {
|
||||
relayChan <- struct {
|
||||
size int
|
||||
buf []byte
|
||||
}{size: size, buf: buff}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go stdReader(stderr)
|
||||
go stdReader(stdout)
|
||||
logger.Println("startChildProcess :", meta.cmd.Args)
|
||||
|
||||
err = meta.cmd.Start()
|
||||
if err == nil {
|
||||
meta.state = protos.ProcessState_Running
|
||||
meta.setState(protos.ProcessState_Running)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest) error {
|
||||
logger.Println("startChildProcess :", *req)
|
||||
if req.Version == "latest" {
|
||||
// 최신 버전을 찾음
|
||||
latest, err := shared.FindLastestVersion(path.Join("./", req.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Version = latest
|
||||
meta, err := prepareProcessLaunch(hc.config.StorageRoot, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
meta := prepareProcessLaunch(req)
|
||||
if err := hc.launch(meta); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// launch가 성공하면 args 저장. this and parent folder
|
||||
if argfile, err := os.Create(path.Join(req.Name, "@args")); err == nil {
|
||||
vers := hc.deploys[req.Name]
|
||||
for _, ver := range vers {
|
||||
if ver.Version == req.Version {
|
||||
ver.Args = meta.args
|
||||
}
|
||||
}
|
||||
|
||||
if argfile, err := os.Create(path.Join(hc.config.StorageRoot, req.Name, "@args")); err == nil {
|
||||
enc := json.NewEncoder(argfile)
|
||||
enc.Encode(meta.cmd.Args)
|
||||
enc.Encode(req.Args)
|
||||
argfile.Close()
|
||||
}
|
||||
if argfile, err := os.Create(path.Join(req.Name, req.Version, "@args")); err == nil {
|
||||
if argfile, err := os.Create(path.Join(hc.config.StorageRoot, req.Name, req.Version, "@args")); err == nil {
|
||||
enc := json.NewEncoder(argfile)
|
||||
enc.Encode(meta.cmd.Args)
|
||||
enc.Encode(req.Args)
|
||||
argfile.Close()
|
||||
}
|
||||
|
||||
hc.childProcs = append(hc.childProcs, meta)
|
||||
|
||||
op := protos.NewOperationClient(hc.client)
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var errNoRunningProcess = errors.New("no running processed")
|
||||
|
||||
func (hc *houstonClient) stopChildProcess(req *shared.StopProcessRequest) error {
|
||||
if req.Version == "latest" {
|
||||
// 최신 버전을 찾음
|
||||
latest, err := shared.FindLastestVersion(path.Join("./", req.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
func (hc *houstonClient) stopChildProcess(req *shared.StopProcessRequest, op protos.OperationClient) error {
|
||||
killer := func(proc *procmeta) {
|
||||
proc.setState(protos.ProcessState_Stopping)
|
||||
if err := proc.cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||
proc.cmd.Process.Signal(os.Kill)
|
||||
}
|
||||
|
||||
req.Version = latest
|
||||
go func() {
|
||||
proc.cmd.Wait()
|
||||
hc.operationChan <- &protos.OperationQueryResponse{
|
||||
Operation: string(shared.Exception),
|
||||
Args: map[string]string{
|
||||
"id": fmt.Sprintf("%d", proc.id),
|
||||
},
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
var remains []*procmeta
|
||||
var killing []*procmeta
|
||||
for _, proc := range hc.childProcs {
|
||||
if proc.state != protos.ProcessState_Running {
|
||||
if !proc.isState(protos.ProcessState_Running) {
|
||||
continue
|
||||
}
|
||||
|
||||
if req.Pid != 0 {
|
||||
if req.Pid == int32(proc.cmd.Process.Pid) {
|
||||
// 해당 pid만 제거
|
||||
killing = append(killing, proc)
|
||||
} else {
|
||||
remains = append(remains, proc)
|
||||
killer(proc)
|
||||
}
|
||||
} else if proc.name == req.Name {
|
||||
if len(req.Version) == 0 {
|
||||
// program 다 정지
|
||||
killing = append(killing, proc)
|
||||
killer(proc)
|
||||
} else if req.Version == proc.version {
|
||||
// program의 특정 버전만 정지
|
||||
killing = append(killing, proc)
|
||||
} else {
|
||||
// 해당 사항 없음
|
||||
remains = append(remains, proc)
|
||||
}
|
||||
} else {
|
||||
// 해당 사항 없음
|
||||
remains = append(remains, proc)
|
||||
}
|
||||
}
|
||||
|
||||
if len(killing) > 0 {
|
||||
for _, proc := range killing {
|
||||
if err := proc.cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||
proc.cmd.Process.Signal(os.Kill)
|
||||
proc.state = protos.ProcessState_Stopping
|
||||
}
|
||||
}
|
||||
|
||||
op := protos.NewOperationClient(hc.client)
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
|
||||
for _, proc := range killing {
|
||||
proc.cmd.Wait()
|
||||
}
|
||||
|
||||
hc.childProcs = remains
|
||||
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errNoRunningProcess
|
||||
}
|
||||
|
||||
func (hc *houstonClient) restartChildProcess(req *shared.RestartProcessRequest) error {
|
||||
if req.Version == "latest" {
|
||||
// 최신 버전을 찾음
|
||||
latest, err := shared.FindLastestVersion(path.Join("./", req.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Version = latest
|
||||
}
|
||||
|
||||
var restarts []*procmeta
|
||||
for _, proc := range hc.childProcs {
|
||||
if proc.name == req.Name {
|
||||
if len(req.Version) == 0 {
|
||||
restarts = append(restarts, proc)
|
||||
} else if req.Version == proc.version {
|
||||
restarts = append(restarts, proc)
|
||||
killer(proc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(restarts) == 0 {
|
||||
return errNoRunningProcess
|
||||
}
|
||||
|
||||
for _, proc := range restarts {
|
||||
if err := proc.cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||
proc.cmd.Process.Signal(os.Kill)
|
||||
}
|
||||
proc.state = protos.ProcessState_Stopping
|
||||
}
|
||||
|
||||
op := protos.NewOperationClient(hc.client)
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
|
||||
for _, proc := range restarts {
|
||||
proc.cmd.Wait()
|
||||
proc.state = protos.ProcessState_Stopped
|
||||
}
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
|
||||
for _, proc := range restarts {
|
||||
if err := hc.launch(proc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hc *houstonClient) uploadFiles(req *shared.UploadRequest) error {
|
||||
if req.Version == "latest" {
|
||||
// 최신 버전을 찾음
|
||||
latest, err := shared.FindLastestVersion(path.Join("./", req.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (hc *houstonClient) restartChildProcess(req *shared.RestartProcessRequest, op protos.OperationClient) error {
|
||||
for _, proc := range hc.childProcs {
|
||||
if proc.cmd.Process.Pid == int(req.Pid) {
|
||||
if len(req.Config) > 0 {
|
||||
// config.json를 먼저 다운로드 시도
|
||||
root := proc.verpath
|
||||
if _, err := download(root, hc.makeDownloadUrl(req.Config), "", nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
req.Version = latest
|
||||
}
|
||||
proc.setState(protos.ProcessState_Restart)
|
||||
op.Refresh(context.Background(), hc.makeOperationQueryRequest())
|
||||
hc.exitChan <- proc.cmd
|
||||
|
||||
for _, child := range hc.childProcs {
|
||||
if child.version == req.Version && child.name == req.Name {
|
||||
child.logUploadChan <- req
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// TODO : 실행 중이 아닌 폴더에서도 대상을 찾는다
|
||||
// deploys
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1 +1,12 @@
|
||||
{}
|
||||
{
|
||||
"houston" : {
|
||||
"client" : {
|
||||
"grpc_server_address" : "10.5.10.100:8080",
|
||||
"http_server_address" : "https://kdcc.action2quare.com/houston"
|
||||
},
|
||||
"server" : {
|
||||
"grpc_port" : 8080,
|
||||
"storage_path" : "/data"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
78
go.mod
78
go.mod
@ -3,26 +3,70 @@ module repositories.action2quare.com/ayo/houston
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/cloudfoundry/gosigar v1.3.12
|
||||
github.com/shirou/gopsutil/v3 v3.23.4
|
||||
golang.org/x/text v0.9.0
|
||||
google.golang.org/grpc v1.55.0
|
||||
google.golang.org/protobuf v1.30.0
|
||||
repositories.action2quare.com/ayo/go-ayo v0.0.0-20230521165809-09cee56768c5
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible
|
||||
github.com/djherbis/times v1.6.0
|
||||
github.com/go-kit/log v0.2.1
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/prometheus/common v0.44.0
|
||||
github.com/prometheus/node_exporter v1.6.1
|
||||
golang.org/x/sys v0.16.0
|
||||
golang.org/x/text v0.14.0
|
||||
google.golang.org/grpc v1.60.1
|
||||
google.golang.org/protobuf v1.32.0
|
||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20240729084947-8e3d6c28f024
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/alecthomas/kingpin/v2 v2.3.2 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||
github.com/beevik/ntp v0.3.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1 // indirect
|
||||
github.com/dennwc/ioctl v1.0.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/ema/qdisc v0.0.0-20230120214811-5b708f463de3 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/onsi/gomega v1.18.1 // indirect
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/hashicorp/go-envparse v0.1.0 // indirect
|
||||
github.com/hodgesds/perf-utils v0.7.0 // indirect
|
||||
github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/jsimonetti/rtnetlink v1.3.2 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/lufia/iostat v1.2.1 // indirect
|
||||
github.com/mattn/go-xmlrpc v0.0.3 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mdlayher/ethtool v0.0.0-20221212131811-ba3b4bc2e02c // indirect
|
||||
github.com/mdlayher/genetlink v1.3.1 // indirect
|
||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||
github.com/mdlayher/socket v0.4.1 // indirect
|
||||
github.com/mdlayher/wifi v0.0.0-20220330172155-a44c70b6d3c8 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/pires/go-proxyproto v0.7.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.5 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
github.com/prometheus-community/go-runit v0.1.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
github.com/safchain/ethtool v0.3.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.1 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
go.mongodb.org/mongo-driver v1.11.6 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
|
||||
howett.net/plist v1.0.0 // indirect
|
||||
)
|
||||
|
||||
266
go.sum
266
go.sum
@ -1,152 +1,182 @@
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cloudfoundry/gosigar v1.3.12 h1:kUvHg+O7DcYKpMSQEJFpNf9kJXLwATBJh5gBwcRxGqI=
|
||||
github.com/cloudfoundry/gosigar v1.3.12/go.mod h1:OKmnKziBrg7zYdKJQ4fDW+B6Aqh/1Vy1StnjqiPEI3I=
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
|
||||
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw=
|
||||
github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cilium/ebpf v0.10.0 h1:nk5HPMeoBXtOzbkZBWym+ZWq1GIiHUsBFXxwewXAHLQ=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1 h1:ue4Es4Xzz255hWQ7NAWzZxuXG+YOV7URzzusLLSe0zU=
|
||||
github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1/go.mod h1:MYsOV9Dgsec3FFSOjywi0QK5r6TeBbdWxdrMGtiYXHA=
|
||||
github.com/dennwc/ioctl v1.0.0 h1:DsWAAjIxRqNcLn9x6mwfuf2pet3iB7aK90K4tF16rLg=
|
||||
github.com/dennwc/ioctl v1.0.0/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
||||
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
||||
github.com/ema/qdisc v0.0.0-20230120214811-5b708f463de3 h1:Jrl8sD8wO34+EE1dV2vhOXrqFAZa/FILDnZRaV28+cw=
|
||||
github.com/ema/qdisc v0.0.0-20230120214811-5b708f463de3/go.mod h1:FhIc0fLYi7f+lK5maMsesDqwYojIOh3VfRs8EVd5YJQ=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
|
||||
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdmPSDFPY=
|
||||
github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc=
|
||||
github.com/hodgesds/perf-utils v0.7.0 h1:7KlHGMuig4FRH5fNw68PV6xLmgTe7jKs9hgAcEAbioU=
|
||||
github.com/hodgesds/perf-utils v0.7.0/go.mod h1:LAklqfDadNKpkxoAJNHpD5tkY0rkZEVdnCEWN5k4QJY=
|
||||
github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973 h1:hk4LPqXIY/c9XzRbe7dA6qQxaT6Axcbny0L/G5a4owQ=
|
||||
github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973/go.mod h1:PoK3ejP3LJkGTzKqRlpvCIFas3ncU02v8zzWDW+g0FY=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jsimonetti/rtnetlink v1.3.2 h1:dcn0uWkfxycEEyNy0IGfx3GrhQ38LH7odjxAghimsVI=
|
||||
github.com/jsimonetti/rtnetlink v1.3.2/go.mod h1:BBu4jZCpTjP6Gk0/wfrO8qcqymnN3g0hoFqObRmUo6U=
|
||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/lufia/iostat v1.2.1 h1:tnCdZBIglgxD47RyD55kfWQcJMGzO+1QBziSQfesf2k=
|
||||
github.com/lufia/iostat v1.2.1/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg=
|
||||
github.com/mattn/go-xmlrpc v0.0.3 h1:Y6WEMLEsqs3RviBrAa1/7qmbGB7DVD3brZIbqMbQdGY=
|
||||
github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mdlayher/ethtool v0.0.0-20221212131811-ba3b4bc2e02c h1:Y7LoKqIgD7vmqJ7+6ZVnADuwUO+m3tGXbf2lK0OvjIw=
|
||||
github.com/mdlayher/ethtool v0.0.0-20221212131811-ba3b4bc2e02c/go.mod h1:i0nPbE+sL2G3OtdIb9SXxW/T4UiAwh6rxPW7zcuX+KQ=
|
||||
github.com/mdlayher/genetlink v1.3.1 h1:roBiPnual+eqtRkKX2Jb8UQN5ZPWnhDCGj/wR6Jlz2w=
|
||||
github.com/mdlayher/genetlink v1.3.1/go.mod h1:uaIPxkWmGk753VVIzDtROxQ8+T+dkHqOI0vB1NA9S/Q=
|
||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/mdlayher/wifi v0.0.0-20220330172155-a44c70b6d3c8 h1:/HCRFfpoICSWHvNrJ356VO4opd9dg/LaU7m8Tzdf39c=
|
||||
github.com/mdlayher/wifi v0.0.0-20220330172155-a44c70b6d3c8/go.mod h1:IqdtNfemiXr50M8tnxLWSFdZKZ9vcI1Mgt0oTrCIS7A=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
|
||||
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o=
|
||||
github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8=
|
||||
github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ=
|
||||
github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
|
||||
github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
|
||||
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/prometheus-community/go-runit v0.1.0 h1:uTWEj/Fn2RoLdfg/etSqwzgYNOYPrARx1BHUN052tGA=
|
||||
github.com/prometheus-community/go-runit v0.1.0/go.mod h1:AvJ9Jo3gAFu2lbM4+qfjdpq30FfiLDJZKbQ015u08IQ=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
|
||||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/node_exporter v1.6.1 h1:Srqr6UAOUDnKhurvYGIYa7GZXuMCwJpzT9KP8uTJ4vw=
|
||||
github.com/prometheus/node_exporter v1.6.1/go.mod h1:+zK+m9vwxu19JHl/kVVmixdCT6fWWHlmcOUHDFpkt0Y=
|
||||
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
|
||||
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
||||
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
||||
github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973 h1:GfSdC6wKfTGcgCS7BtzF5694Amne1pGCSTY252WhlEY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
go.mongodb.org/mongo-driver v1.11.6 h1:XM7G6PjiGAO5betLF13BIa5TlLUUE3uJ/2Ox3Lz1K+o=
|
||||
go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
|
||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA=
|
||||
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
|
||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
repositories.action2quare.com/ayo/go-ayo v0.0.0-20230521165809-09cee56768c5 h1:EobNJQwZ/TyRRtXY9XhJslN80V+sKoAztsda3x+ISE0=
|
||||
repositories.action2quare.com/ayo/go-ayo v0.0.0-20230521165809-09cee56768c5/go.mod h1:3gLLbyiq4cOEraSiY6wpYWdcWRPcQKIcs0TfQ/Vwhoc=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20240729084947-8e3d6c28f024 h1:WdvW4BJHoBwXqNsfEgOAZai7L9iHqRCZ7PZL0cwOULE=
|
||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20240729084947-8e3d6c28f024/go.mod h1:XA8+hQtUNh956T+kAbJKkUtMl5HUWj83knvdBvvPS5s=
|
||||
|
||||
37
houston.sh
Normal file
37
houston.sh
Normal file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
HOUSTON_PATH="./houston"
|
||||
UPDATE_DIR="houston.update"
|
||||
|
||||
run_houston() {
|
||||
if [ -f "$HOUSTON_PATH" ]; then
|
||||
"$HOUSTON_PATH" "$@"
|
||||
return $?
|
||||
else
|
||||
echo "houston 실행 파일이 없습니다."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
while true; do
|
||||
echo "현재 버전의 houston을 실행합니다."
|
||||
run_houston "$@"
|
||||
|
||||
# houston.update 폴더가 존재하는지 확인
|
||||
if [ -d "$UPDATE_DIR" ]; then
|
||||
echo "새로운 업데이트 폴더 발견. 업데이트를 진행합니다."
|
||||
# houston.update 폴더 내의 모든 파일을 현재 폴더로 복사
|
||||
cp -R "$UPDATE_DIR"/* .
|
||||
# 실행 권한 부여 (필요한 경우)
|
||||
chmod +x "$HOUSTON_PATH"
|
||||
# 업데이트 폴더 삭제
|
||||
rm -rf "$UPDATE_DIR"
|
||||
echo "업데이트 완료 및 업데이트 폴더 삭제. houston을 다시 시작합니다."
|
||||
else
|
||||
echo "업데이트 폴더가 없습니다. 스크립트 실행을 종료합니다."
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo "houston 실행 및 업데이트 스크립트 종료"
|
||||
exit $?
|
||||
@ -1,20 +1,16 @@
|
||||
package houston_test
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"repositories.action2quare.com/ayo/houston/client"
|
||||
)
|
||||
|
||||
func TestOperationServer(t *testing.T) {
|
||||
hc, _ := client.NewClient("localhost:8080", "http://localhost/commandcenter")
|
||||
for i := 0; ; i++ {
|
||||
hc.SetReportMetrics(map[string]float32{
|
||||
"count": float32(i),
|
||||
})
|
||||
time.Sleep(1300 * time.Millisecond)
|
||||
}
|
||||
fmt.Println(path.Join("a", "b", "/"))
|
||||
fmt.Println(path.Join("a", "b/"))
|
||||
fmt.Println(path.Join("a", "b/", "/"))
|
||||
fmt.Println(path.Join("a", "b/", "/", "/"))
|
||||
|
||||
// token, _ := getMicrosoftAuthoizationToken("30330e18-f407-4e35-a6d6-b734b9fe9ee9", "VTr8Q~VBAUAOSmFiHM~bjgszYXBm9nuGBQCk8cLq")
|
||||
//go func() {
|
||||
|
||||
38
main_client.go
Normal file
38
main_client.go
Normal file
@ -0,0 +1,38 @@
|
||||
//go:build client
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
"repositories.action2quare.com/ayo/houston/client"
|
||||
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flagx.Parse()
|
||||
|
||||
hc, err := client.NewClient(true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
server := &http.Server{Addr: ":9100", Handler: nil}
|
||||
|
||||
go func() {
|
||||
logger.Println("listen /metrics")
|
||||
server.ListenAndServe()
|
||||
}()
|
||||
|
||||
hc.Start()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
server.Shutdown(ctx)
|
||||
cancel()
|
||||
}
|
||||
15
main_server.go
Normal file
15
main_server.go
Normal file
@ -0,0 +1,15 @@
|
||||
//go:build !client
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||
"repositories.action2quare.com/ayo/houston/server"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flagx.Parse()
|
||||
|
||||
svr := server.NewServer()
|
||||
svr.Start()
|
||||
}
|
||||
16
make_houston_package.ps1
Normal file
16
make_houston_package.ps1
Normal file
@ -0,0 +1,16 @@
|
||||
# $ErrorActionPreference = 'SilentlyContinue'
|
||||
|
||||
del houston.zip
|
||||
|
||||
$Env:GOOS="linux"
|
||||
$Env:GOARCH="amd64"
|
||||
|
||||
go get repositories.action2quare.com/ayo/gocommon
|
||||
go mod tidy
|
||||
|
||||
go build -ldflags="-s -w" -tags=client .
|
||||
|
||||
Compress-Archive -Path config.json -Update -DestinationPath houston.zip
|
||||
Compress-Archive -Path houston -Update -DestinationPath houston.zip
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import "protos/empty.proto";
|
||||
service Operation {
|
||||
rpc Query(stream OperationQueryRequest) returns (stream OperationQueryResponse) {}
|
||||
rpc Refresh(OperationQueryRequest) returns (Empty) {}
|
||||
rpc ReportDeployingProgress(DeployingProgress) returns (Empty) {}
|
||||
}
|
||||
|
||||
message VersionAndArgs {
|
||||
@ -19,6 +20,9 @@ message DeployedVersions {
|
||||
|
||||
message OperationQueryRequest {
|
||||
string hostname = 1;
|
||||
string public_ip = 4;
|
||||
string private_ip =5;
|
||||
|
||||
repeated ProcessDescription procs = 2;
|
||||
repeated DeployedVersions deploys = 3;
|
||||
}
|
||||
@ -27,7 +31,8 @@ enum ProcessState {
|
||||
Stopped = 0;
|
||||
Stopping = 1;
|
||||
Running = 2;
|
||||
Error = 3;
|
||||
Restart = 3;
|
||||
Error = 4;
|
||||
}
|
||||
|
||||
message ProcessDescription {
|
||||
@ -36,11 +41,18 @@ message ProcessDescription {
|
||||
string version = 3;
|
||||
ProcessState state = 4;
|
||||
int32 pid = 5;
|
||||
int32 stdout_size = 6;
|
||||
int32 stderr_size = 7;
|
||||
}
|
||||
|
||||
message OperationQueryResponse {
|
||||
string operation = 1;
|
||||
map<string, string> args = 2;
|
||||
}
|
||||
|
||||
message DeployingProgress {
|
||||
string hostname = 1;
|
||||
string name = 2;
|
||||
string version = 3;
|
||||
string state = 4;
|
||||
int64 progress = 5;
|
||||
int64 total = 6;
|
||||
}
|
||||
@ -2,39 +2,86 @@ package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"repositories.action2quare.com/ayo/go-ayo/logger"
|
||||
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
"repositories.action2quare.com/ayo/houston/shared"
|
||||
)
|
||||
|
||||
/*
|
||||
*
|
||||
현재 접속 중인 Agent 목록을 보여줍니다.
|
||||
- http method : GET
|
||||
*/
|
||||
const (
|
||||
sub_folder_name_deploys = string("_deploys")
|
||||
sub_folder_name_downloads = string("_downloads")
|
||||
)
|
||||
|
||||
func (h *houstonHandler) GetAgents(w http.ResponseWriter, r *http.Request) {
|
||||
logger.Println("GetAgents")
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
enc.Encode(h.Operation().Hosts())
|
||||
allHosts := h.Operation().Hosts()
|
||||
enc.Encode(allHosts)
|
||||
}
|
||||
|
||||
func readTagsFromFile(paths ...string) string {
|
||||
raw, _ := os.ReadFile(path.Join(paths...))
|
||||
if len(raw) > 0 {
|
||||
tag := string(raw)
|
||||
return strings.Trim(tag, "\n")
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (h *houstonHandler) GetDeploySources(w http.ResponseWriter, r *http.Request) {
|
||||
files, err := os.ReadDir("deploys")
|
||||
logger.Println("GetDeploySources")
|
||||
|
||||
files, err := os.ReadDir(h.deployPath)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
getVersions := func(name string) []string {
|
||||
var out []string
|
||||
files, _ := os.ReadDir(path.Join("deploys", name))
|
||||
for _, fd := range files {
|
||||
vers, _ := os.ReadDir(path.Join(h.deployPath, name))
|
||||
mytags := readTagsFromFile(h.deployPath, name, "@tags")
|
||||
out := []string{
|
||||
mytags,
|
||||
}
|
||||
for _, fd := range vers {
|
||||
if fd.IsDir() {
|
||||
out = append(out, fd.Name())
|
||||
ver := fd.Name()
|
||||
files, _ := os.ReadDir(path.Join(h.deployPath, name, ver))
|
||||
vertags := readTagsFromFile(h.deployPath, name, ver, "@tags")
|
||||
if len(files) > 0 {
|
||||
for _, file := range files {
|
||||
if strings.HasPrefix(file.Name(), "@") {
|
||||
continue
|
||||
}
|
||||
|
||||
downloadpath := path.Join(sub_folder_name_deploys, name, ver, file.Name())
|
||||
ver = fmt.Sprintf("%s:%s", ver+mytags+vertags, downloadpath)
|
||||
break
|
||||
}
|
||||
}
|
||||
out = append(out, ver)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@ -57,8 +104,9 @@ func (h *houstonHandler) UploadDeploySource(w http.ResponseWriter, r *http.Reque
|
||||
// <input type="submit" value="업로드">
|
||||
// </form>
|
||||
file, header, err := r.FormFile("file")
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@ -66,7 +114,7 @@ func (h *houstonHandler) UploadDeploySource(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
contents, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -75,10 +123,23 @@ func (h *houstonHandler) UploadDeploySource(w http.ResponseWriter, r *http.Reque
|
||||
name := r.FormValue("name")
|
||||
ext := path.Ext(header.Filename)
|
||||
|
||||
// deploys 폴더는 파일시스템 서비스이므로 다운로드 가능
|
||||
filename := path.Join("deploys", name, version, name+ext)
|
||||
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println("UploadDeploySource :", name, version)
|
||||
|
||||
var filename string
|
||||
|
||||
if version == "config" {
|
||||
filename = path.Join(h.deployPath, name, version, "config"+ext)
|
||||
tags := readTagsFromFile(h.deployPath, name, version, "@tags")
|
||||
if !strings.Contains(tags, "#hidden") {
|
||||
tags = tags + "#hidden"
|
||||
os.WriteFile(path.Join(h.deployPath, name, version, "@tags"), []byte(tags), 0644)
|
||||
}
|
||||
} else {
|
||||
filename = path.Join(h.deployPath, name, version, name+ext)
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(path.Dir(filename), 0775); err != nil {
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -86,12 +147,78 @@ func (h *houstonHandler) UploadDeploySource(w http.ResponseWriter, r *http.Reque
|
||||
// 파일 저장
|
||||
err = os.WriteFile(filename, contents, 0644)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *houstonHandler) DeleteDeploySource(w http.ResponseWriter, r *http.Request) {
|
||||
// <form action="/houston" method="post" enctype="multipart/form-data">
|
||||
// <input type="text" name="name">
|
||||
// <input type="text" name="version">
|
||||
// </form>
|
||||
version := r.FormValue("version")
|
||||
name := r.FormValue("name")
|
||||
|
||||
logger.Println("DeleteDeploySource :", name, version)
|
||||
if len(version) == 0 || len(name) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// deploys 폴더는 파일시스템 서비스이므로 다운로드 가능
|
||||
targetpath := path.Join(h.deployPath, name, version)
|
||||
logger.Println("DeleteDeploySource :", name, version, targetpath)
|
||||
|
||||
if err := os.RemoveAll(targetpath); err != nil {
|
||||
logger.Println("deleteDeploySource failed :", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *houstonHandler) findLastestConfigFile(name string) (string, error) {
|
||||
logger.Println("findLastestConfigFile :", name)
|
||||
configFiles, err := os.ReadDir(path.Join(h.deployPath, name, "config"))
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
logger.Println("findLastestConfigFile failed :", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
var cf fs.FileInfo
|
||||
for _, file := range configFiles {
|
||||
if file.IsDir() {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(file.Name(), "config.") {
|
||||
test, err := file.Info()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if cf == nil {
|
||||
cf = test
|
||||
} else if test.ModTime().After(cf.ModTime()) {
|
||||
cf = test
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cf != nil {
|
||||
logger.Println("findLastestConfigFile cf found :", cf.Name())
|
||||
return path.Join(sub_folder_name_deploys, name, "config", cf.Name()), nil
|
||||
}
|
||||
|
||||
logger.Println("findLastestConfigFile cf NOT found")
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (h *houstonHandler) Deploy(w http.ResponseWriter, r *http.Request) {
|
||||
// <form action="/houston" method="post" enctype="multipart/form-data">
|
||||
// <input type="text" name="name">
|
||||
@ -103,10 +230,12 @@ func (h *houstonHandler) Deploy(w http.ResponseWriter, r *http.Request) {
|
||||
version := r.FormValue("version")
|
||||
traws := r.FormValue("targets")
|
||||
|
||||
logger.Println("Deploy :", name, version, traws)
|
||||
|
||||
var targets []string
|
||||
if len(traws) > 0 {
|
||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@ -117,11 +246,11 @@ func (h *houstonHandler) Deploy(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
relPath := path.Join("deploys", name, version)
|
||||
relPath := path.Join(h.deployPath, name, version)
|
||||
files, err := os.ReadDir(relPath)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -132,6 +261,10 @@ func (h *houstonHandler) Deploy(w http.ResponseWriter, r *http.Request) {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fd.Name(), "@") {
|
||||
continue
|
||||
}
|
||||
|
||||
fi, _ := fd.Info()
|
||||
if fi.ModTime().After(latestTime) {
|
||||
latestFilename = fi.Name()
|
||||
@ -143,11 +276,58 @@ func (h *houstonHandler) Deploy(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var configPath string
|
||||
if name != "houston" {
|
||||
// houston은 config를 포함하여 배포
|
||||
configPath, err = h.findLastestConfigFile(name)
|
||||
if err != nil {
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
h.Operation().Deploy(MakeDeployRequest(
|
||||
shared.DeployRequest{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Url: path.Join(relPath, latestFilename),
|
||||
Url: path.Join(sub_folder_name_deploys, name, version, latestFilename),
|
||||
Config: configPath,
|
||||
},
|
||||
targets,
|
||||
))
|
||||
}
|
||||
|
||||
func (h *houstonHandler) Undeploy(w http.ResponseWriter, r *http.Request) {
|
||||
// <form action="/houston" method="post" enctype="multipart/form-data">
|
||||
// <input type="text" name="name">
|
||||
// <input type="text" name="version">
|
||||
// <input type="text" name="targets">
|
||||
// </form>
|
||||
name := r.FormValue("name")
|
||||
version := r.FormValue("version")
|
||||
traws := r.FormValue("targets")
|
||||
|
||||
logger.Println("Undeploy :", name, version, traws)
|
||||
|
||||
var targets []string
|
||||
if len(traws) > 0 {
|
||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(name) == 0 || len(version) == 0 || len(targets) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
h.Operation().Withdraw(MakeWithdrawRequest(
|
||||
shared.WithdrawRequest{
|
||||
Name: name,
|
||||
Version: version,
|
||||
},
|
||||
targets,
|
||||
))
|
||||
@ -163,13 +343,15 @@ func (h *houstonHandler) StartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
// </form>
|
||||
name := r.FormValue("name")
|
||||
version := r.FormValue("version")
|
||||
args := r.FormValue("args")
|
||||
argsline := r.FormValue("args")
|
||||
traws := r.FormValue("targets")
|
||||
|
||||
logger.Println("StartProcess :", name, version, argsline, traws)
|
||||
|
||||
var targets []string
|
||||
if len(traws) > 0 {
|
||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@ -180,6 +362,28 @@ func (h *houstonHandler) StartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
re := regexp.MustCompile(`[^\s"']+|"([^"]*)"|'([^']*)`)
|
||||
argsTemp := re.FindAllString(argsline, -1)
|
||||
var args []string
|
||||
for _, arg := range argsTemp {
|
||||
arg = strings.Trim(arg, "\n ")
|
||||
if strings.HasPrefix(arg, `"`) && len(args) > 0 {
|
||||
lastarg := args[len(args)-1]
|
||||
if strings.HasSuffix(lastarg, "=") {
|
||||
args[len(args)-1] = lastarg + arg
|
||||
} else {
|
||||
args = append(args, arg)
|
||||
}
|
||||
} else {
|
||||
args = append(args, arg)
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
h.Operation().StartProcess(MakeStartProcessRequest(shared.StartProcessRequest{
|
||||
Name: name,
|
||||
Version: version,
|
||||
@ -196,6 +400,8 @@ func (h *houstonHandler) StopProcess(w http.ResponseWriter, r *http.Request) {
|
||||
// <input type="submit" value="업로드">
|
||||
// </form>
|
||||
name := r.FormValue("name")
|
||||
logger.Println("StopProcess :", name)
|
||||
|
||||
if len(name) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
@ -208,7 +414,7 @@ func (h *houstonHandler) StopProcess(w http.ResponseWriter, r *http.Request) {
|
||||
var targets []string
|
||||
if len(traws) > 0 {
|
||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@ -221,6 +427,60 @@ func (h *houstonHandler) StopProcess(w http.ResponseWriter, r *http.Request) {
|
||||
Version: version,
|
||||
Pid: int32(pid),
|
||||
}, targets))
|
||||
|
||||
h.Operation().Upload(MakeUploadRequest(shared.UploadRequest{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Url: "upload",
|
||||
DeleteAfterUploaded: "true",
|
||||
}, targets))
|
||||
}
|
||||
|
||||
func (h *houstonHandler) RestartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
// <form action="/houston" method="post" enctype="multipart/form-data">
|
||||
// <input type="text" name="name">
|
||||
// <input type="text" name="target">
|
||||
// <input type="text" name="pid">
|
||||
// <input type="text" name="config">
|
||||
// </form>
|
||||
pidstr := r.FormValue("pid")
|
||||
target := r.FormValue("target")
|
||||
name := r.FormValue("name")
|
||||
logger.Println("RestartProcess :", name, pidstr, target)
|
||||
|
||||
if len(target) == 0 || len(pidstr) == 0 || len(name) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
deployConfig := false
|
||||
configstr := r.FormValue("config")
|
||||
if len(configstr) > 0 {
|
||||
deployConfig, _ = strconv.ParseBool(configstr)
|
||||
}
|
||||
|
||||
pid, err := strconv.ParseInt(pidstr, 10, 0)
|
||||
if err != nil {
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var configPath string
|
||||
if deployConfig {
|
||||
configPath, err = h.findLastestConfigFile(name)
|
||||
if err != nil {
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
h.Operation().RestartProcess(MakeRestartRequest(shared.RestartProcessRequest{
|
||||
Name: name,
|
||||
Pid: int32(pid),
|
||||
Config: configPath,
|
||||
}, []string{target}))
|
||||
}
|
||||
|
||||
func (h *houstonHandler) UploadLogs(w http.ResponseWriter, r *http.Request) {
|
||||
@ -232,6 +492,8 @@ func (h *houstonHandler) UploadLogs(w http.ResponseWriter, r *http.Request) {
|
||||
// <input type="submit" value="업로드">
|
||||
// </form>
|
||||
name := r.FormValue("name")
|
||||
logger.Println("UploadLogs :", name)
|
||||
|
||||
if len(name) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
@ -245,7 +507,7 @@ func (h *houstonHandler) UploadLogs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
var targets []string
|
||||
if err := json.Unmarshal([]byte(traws), &targets); err != nil {
|
||||
logger.Error(err)
|
||||
logger.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@ -265,22 +527,29 @@ func (h *houstonHandler) GetLogFileLinks(w http.ResponseWriter, r *http.Request)
|
||||
// </form>
|
||||
name := r.FormValue("name")
|
||||
version := r.FormValue("version")
|
||||
logger.Println("GetLogFileLinks :", name, version)
|
||||
|
||||
if len(name) == 0 || len(version) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
logfiles, err := os.ReadDir(path.Join("downloads", name, version))
|
||||
root := path.Join(h.downloadPath, name, version)
|
||||
logfiles, err := os.ReadDir(root)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var out []string
|
||||
for _, lf := range logfiles {
|
||||
out = append(out, lf.Name())
|
||||
out = append(out, path.Join(sub_folder_name_downloads, name, version, lf.Name()))
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
enc.Encode(out)
|
||||
}
|
||||
|
||||
func (h *houstonHandler) GetDeployingProgress(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(h.Operation().DeplyingProgress())
|
||||
}
|
||||
|
||||
@ -1,33 +1,36 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"repositories.action2quare.com/ayo/go-ayo/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMaxMemory = 32 << 10 // 32 KB
|
||||
"repositories.action2quare.com/ayo/gocommon"
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
)
|
||||
|
||||
type HoustonServerWithHandler interface {
|
||||
HoustonServer
|
||||
RegisterHandlers(serveMux *http.ServeMux, prefix string) error
|
||||
RegisterHandlers(serveMux gocommon.ServerMuxInterface, prefix string) error
|
||||
}
|
||||
|
||||
type houstonHandler struct {
|
||||
HoustonServer
|
||||
methods map[string]reflect.Method
|
||||
methods map[string]reflect.Method
|
||||
deployPath string
|
||||
downloadPath string
|
||||
maingateApiToken string
|
||||
}
|
||||
|
||||
func NewHoustonHandler() HoustonServerWithHandler {
|
||||
func NewHoustonHandler(apiToken string) HoustonServerWithHandler {
|
||||
var tmp *houstonHandler
|
||||
|
||||
methods := make(map[string]reflect.Method)
|
||||
@ -37,30 +40,94 @@ func NewHoustonHandler() HoustonServerWithHandler {
|
||||
methods[strings.ToLower(method.Name)] = method
|
||||
}
|
||||
return &houstonHandler{
|
||||
HoustonServer: NewServer(),
|
||||
methods: methods,
|
||||
HoustonServer: NewServer(),
|
||||
methods: methods,
|
||||
maingateApiToken: apiToken,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *houstonHandler) RegisterHandlers(serveMux *http.ServeMux, prefix string) error {
|
||||
serveMux.Handle("/"+path.Join(prefix, "houston"), h)
|
||||
func (h *houstonHandler) RegisterHandlers(serveMux gocommon.ServerMuxInterface, prefix string) error {
|
||||
config := loadServerConfig()
|
||||
storagePath := config.StorageRoot
|
||||
h.deployPath = path.Join(storagePath, sub_folder_name_deploys)
|
||||
h.downloadPath = path.Join(storagePath, sub_folder_name_downloads)
|
||||
|
||||
dfsx := http.FileServer(http.Dir("./deploys"))
|
||||
serveMux.Handle(
|
||||
"/"+path.Join(prefix, "deploys", "/"),
|
||||
http.StripPrefix(fmt.Sprintf("/%s/deploys", prefix), dfsx))
|
||||
if err := os.MkdirAll(h.deployPath, 0775); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ufsx := http.FileServer(http.Dir("./downloads"))
|
||||
serveMux.Handle(
|
||||
"/"+path.Join(prefix, "downloads", "/"),
|
||||
http.StripPrefix(fmt.Sprintf("/%s/downloads", prefix), ufsx))
|
||||
if err := os.MkdirAll(h.downloadPath, 0775); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serveMux.HandleFunc("/"+path.Join(prefix, "upload"), func(w http.ResponseWriter, r *http.Request) {
|
||||
if len(prefix) > 0 {
|
||||
prefix = "/" + prefix
|
||||
}
|
||||
serveMux.Handle(prefix, h)
|
||||
|
||||
fsx := http.FileServer(http.Dir(h.deployPath))
|
||||
deployPrefix := fmt.Sprintf("%s/%s/", prefix, sub_folder_name_deploys)
|
||||
logger.Printf("houstonHandler registed. deployPath : %s -> %s", fmt.Sprintf("%s/%s/", prefix, sub_folder_name_deploys), h.deployPath)
|
||||
serveMux.HandleFunc(fmt.Sprintf("%s/%s/", prefix, sub_folder_name_deploys), func(w http.ResponseWriter, r *http.Request) {
|
||||
p := strings.TrimPrefix(r.URL.Path, deployPrefix)
|
||||
rp := strings.TrimPrefix(r.URL.RawPath, deployPrefix)
|
||||
|
||||
h := md5.New()
|
||||
src := strings.TrimLeft(r.URL.Path, fmt.Sprintf("/%s/", prefix))
|
||||
|
||||
h.Write([]byte(src))
|
||||
at := hex.EncodeToString(h.Sum(nil))
|
||||
|
||||
if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) && at == r.Header.Get("As-X-UrlHash") {
|
||||
r2 := new(http.Request)
|
||||
*r2 = *r
|
||||
r2.URL = new(url.URL)
|
||||
*r2.URL = *r.URL
|
||||
r2.URL.Path = p
|
||||
r2.URL.RawPath = rp
|
||||
fsx.ServeHTTP(w, r2)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
|
||||
// config는 접근하기 편하게 단축 경로 제공
|
||||
serveMux.HandleFunc("/config/", func(w http.ResponseWriter, r *http.Request) {
|
||||
logger.Println("config url.path :", r.URL.Path)
|
||||
testhash := md5.New()
|
||||
testhash.Write([]byte(r.URL.Path))
|
||||
at := hex.EncodeToString(testhash.Sum(nil))
|
||||
hash := r.Header.Get("As-X-UrlHash")
|
||||
logger.Println("config at = hash :", at, hash)
|
||||
if at == hash {
|
||||
urlpath := strings.TrimPrefix(r.URL.Path, "/config/")
|
||||
dir := path.Dir(urlpath)
|
||||
file := path.Base(urlpath)
|
||||
sourceFile := path.Join(h.deployPath, dir, "config", file)
|
||||
logger.Println("config dest :", sourceFile)
|
||||
bt, err := os.ReadFile(sourceFile)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
logger.Println("config file is missing :", sourceFile)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
} else {
|
||||
if _, err = w.Write(bt); err != nil {
|
||||
logger.Println("config write failed :", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
|
||||
ufsx := http.FileServer(http.Dir(h.downloadPath))
|
||||
serveMux.Handle(fmt.Sprintf("%s/%s/", prefix, sub_folder_name_downloads), http.StripPrefix(fmt.Sprintf("%s/%s/", prefix, sub_folder_name_downloads), ufsx))
|
||||
|
||||
serveMux.HandleFunc(fmt.Sprintf("%s/upload", prefix), func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
s := recover()
|
||||
if s != nil {
|
||||
logger.Println(s)
|
||||
debug.PrintStack()
|
||||
logger.Error(s)
|
||||
}
|
||||
io.Copy(io.Discard, r.Body)
|
||||
r.Body.Close()
|
||||
@ -69,12 +136,14 @@ func (h *houstonHandler) RegisterHandlers(serveMux *http.ServeMux, prefix string
|
||||
name := r.Header.Get("Houston-Service-Name")
|
||||
version := r.Header.Get("Houston-Service-Version")
|
||||
filename := r.Header.Get("Houston-Service-Filename")
|
||||
dir := fmt.Sprintf("./downloads/%s/%s", name, version)
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err == nil {
|
||||
file, _ := os.Create(path.Join(dir, filename))
|
||||
if file != nil {
|
||||
defer file.Close()
|
||||
if _, err = io.Copy(file, r.Body); err != nil {
|
||||
dir := path.Join(h.downloadPath, name, version)
|
||||
if err := os.MkdirAll(dir, 0775); err == nil {
|
||||
filepath := path.Join(dir, filename)
|
||||
// filepath가 이미 있으면 append
|
||||
localfile, _ := os.OpenFile(filepath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
|
||||
if localfile != nil {
|
||||
defer localfile.Close()
|
||||
if _, err = io.Copy(localfile, r.Body); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
} else {
|
||||
@ -122,15 +191,14 @@ func (h *houstonHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if r.PostForm == nil {
|
||||
r.ParseMultipartForm(defaultMaxMemory)
|
||||
}
|
||||
|
||||
args := []reflect.Value{
|
||||
reflect.ValueOf(h),
|
||||
reflect.ValueOf(w),
|
||||
reflect.ValueOf(r),
|
||||
}
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
|
||||
method.Func.Call(args)
|
||||
}
|
||||
|
||||
@ -4,11 +4,14 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"repositories.action2quare.com/ayo/go-ayo/logger"
|
||||
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
"repositories.action2quare.com/ayo/houston/shared"
|
||||
"repositories.action2quare.com/ayo/houston/shared/protos"
|
||||
)
|
||||
@ -19,20 +22,20 @@ type opdef struct {
|
||||
}
|
||||
|
||||
type ProcessSnapshot struct {
|
||||
Name string
|
||||
Args []string
|
||||
Version string
|
||||
State protos.ProcessState
|
||||
Pid int32
|
||||
StdoutSize int32
|
||||
StderrSize int32
|
||||
Name string `json:"name"`
|
||||
Args []string `json:"args"`
|
||||
Version string `json:"version"`
|
||||
State protos.ProcessState `json:"state"`
|
||||
Pid int32 `json:"pid"`
|
||||
}
|
||||
|
||||
type hostWithChan struct {
|
||||
Hostname string
|
||||
Procs []*protos.ProcessDescription
|
||||
Deploys map[string][]*protos.VersionAndArgs
|
||||
opChan chan *opdef
|
||||
Hostname string
|
||||
PrivateIp string
|
||||
PublicIp string
|
||||
Procs []*protos.ProcessDescription `json:"procs"`
|
||||
Deploys map[string][]*protos.VersionAndArgs `json:"deploys"`
|
||||
opChan chan *opdef
|
||||
}
|
||||
|
||||
func makeHostWithChan(desc *protos.OperationQueryRequest) *hostWithChan {
|
||||
@ -42,9 +45,11 @@ func makeHostWithChan(desc *protos.OperationQueryRequest) *hostWithChan {
|
||||
}
|
||||
|
||||
return &hostWithChan{
|
||||
Hostname: desc.GetHostname(),
|
||||
Procs: desc.Procs,
|
||||
Deploys: newdeploys,
|
||||
PrivateIp: desc.PrivateIp,
|
||||
PublicIp: desc.PublicIp,
|
||||
Hostname: desc.GetHostname(),
|
||||
Procs: desc.Procs,
|
||||
Deploys: newdeploys,
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +65,27 @@ func (pc *hostWithChan) makeOpChan() *hostWithChan {
|
||||
|
||||
type hostPool struct {
|
||||
sync.Mutex
|
||||
hosts map[string]*hostWithChan
|
||||
hosts map[string]*hostWithChan
|
||||
exportChan chan string
|
||||
}
|
||||
|
||||
type deployingProgress struct {
|
||||
*protos.DeployingProgress
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
type deployingBoard struct {
|
||||
sync.Mutex
|
||||
progs []deployingProgress
|
||||
}
|
||||
|
||||
func (db *deployingBoard) clone() (out []deployingProgress) {
|
||||
db.Lock()
|
||||
defer db.Unlock()
|
||||
|
||||
out = make([]deployingProgress, len(db.progs))
|
||||
copy(out, db.progs)
|
||||
return
|
||||
}
|
||||
|
||||
func (sp *hostPool) regist(desc *protos.OperationQueryRequest) (string, chan *opdef) {
|
||||
@ -72,10 +97,29 @@ func (sp *hostPool) regist(desc *protos.OperationQueryRequest) (string, chan *op
|
||||
} else {
|
||||
host = makeHostWithChan(desc).withOpChan(host.opChan)
|
||||
}
|
||||
sp.hosts[desc.Hostname] = host
|
||||
|
||||
test, _ := json.Marshal(sp.hosts)
|
||||
logger.Println(string(test))
|
||||
logger.Println("houston agent registered :", desc.Hostname, desc.PrivateIp, desc.PublicIp)
|
||||
go func(prvip string, pubip string) {
|
||||
if len(prvip) > 0 {
|
||||
address := net.JoinHostPort(prvip, "9100")
|
||||
if conn, _ := net.DialTimeout("tcp", address, 3*time.Second); conn != nil {
|
||||
conn.Close()
|
||||
sp.exportChan <- "+" + address
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(pubip) > 0 {
|
||||
address := net.JoinHostPort(pubip, "9100")
|
||||
if conn, _ := net.DialTimeout("tcp", address, 3*time.Second); conn != nil {
|
||||
conn.Close()
|
||||
sp.exportChan <- "+" + address
|
||||
return
|
||||
}
|
||||
}
|
||||
}(desc.PrivateIp, desc.PublicIp)
|
||||
|
||||
sp.hosts[desc.Hostname] = host
|
||||
return desc.Hostname, host.opChan
|
||||
}
|
||||
|
||||
@ -88,21 +132,24 @@ func (sp *hostPool) refresh(desc *protos.OperationQueryRequest) {
|
||||
host = makeHostWithChan(desc).withOpChan(host.opChan)
|
||||
sp.hosts[desc.Hostname] = host
|
||||
}
|
||||
|
||||
test, _ := json.Marshal(sp.hosts)
|
||||
logger.Println(string(test))
|
||||
}
|
||||
|
||||
func (sp *hostPool) unregist(key string) {
|
||||
sp.Lock()
|
||||
defer sp.Unlock()
|
||||
|
||||
host := sp.hosts[key]
|
||||
if host != nil {
|
||||
sp.exportChan <- "-" + host.PublicIp
|
||||
sp.exportChan <- "-" + host.PrivateIp
|
||||
}
|
||||
|
||||
delete(sp.hosts, key)
|
||||
}
|
||||
|
||||
type hostSnapshot struct {
|
||||
Procs []ProcessSnapshot
|
||||
Deploys map[string][]*protos.VersionAndArgs
|
||||
Procs []ProcessSnapshot `json:"procs"`
|
||||
Deploys map[string][]*protos.VersionAndArgs `json:"deploys"`
|
||||
}
|
||||
|
||||
func (sp *hostPool) allHosts() map[string]hostSnapshot {
|
||||
@ -114,13 +161,11 @@ func (sp *hostPool) allHosts() map[string]hostSnapshot {
|
||||
procs := make([]ProcessSnapshot, 0, len(v.Procs))
|
||||
for _, p := range v.Procs {
|
||||
procs = append(procs, ProcessSnapshot{
|
||||
Name: p.Name,
|
||||
Args: p.Args,
|
||||
Version: p.Version,
|
||||
State: p.State,
|
||||
Pid: p.Pid,
|
||||
StdoutSize: p.StdoutSize,
|
||||
StderrSize: p.StderrSize,
|
||||
Name: p.Name,
|
||||
Args: p.Args,
|
||||
Version: p.Version,
|
||||
State: p.State,
|
||||
Pid: p.Pid,
|
||||
})
|
||||
}
|
||||
out[hn] = hostSnapshot{
|
||||
@ -147,6 +192,7 @@ func (sp *hostPool) query(filter func(*hostWithChan) bool) []*hostWithChan {
|
||||
type operationServer struct {
|
||||
protos.UnimplementedOperationServer
|
||||
hp hostPool
|
||||
db deployingBoard
|
||||
}
|
||||
|
||||
func marshal(argval reflect.Value, output map[string]string) map[string]string {
|
||||
@ -163,6 +209,12 @@ func marshal(argval reflect.Value, output map[string]string) map[string]string {
|
||||
marshal(argval.Field(i), output)
|
||||
} else if argval.Field(i).CanInt() {
|
||||
output[argval.Type().Field(i).Name] = fmt.Sprintf("%d", argval.Field(i).Int())
|
||||
} else if argval.Field(i).Kind() == reflect.Array || argval.Field(i).Kind() == reflect.Slice {
|
||||
var conv []string
|
||||
for j := 0; j < argval.Field(i).Len(); j++ {
|
||||
conv = append(conv, argval.Field(i).Index(j).String())
|
||||
}
|
||||
output[argval.Type().Field(i).Name] = strings.Join(conv, "\n")
|
||||
} else {
|
||||
output[argval.Type().Field(i).Name] = argval.Field(i).String()
|
||||
}
|
||||
@ -171,15 +223,19 @@ func marshal(argval reflect.Value, output map[string]string) map[string]string {
|
||||
}
|
||||
|
||||
func (os *operationServer) Query(svr protos.Operation_QueryServer) error {
|
||||
// 서버는 업데이트가 있는지 확인하고 있으면 stream에 응답을 보낸다.
|
||||
// 업데이트가 없으면 대기
|
||||
desc, err := svr.Recv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hostname := desc.Hostname
|
||||
key, opChan := os.hp.regist(desc)
|
||||
defer os.hp.unregist(key)
|
||||
defer func() {
|
||||
logger.Println("operationServer.Query : houston client unregistered ", hostname)
|
||||
os.hp.unregist(key)
|
||||
}()
|
||||
|
||||
logger.Println("operationServer.Query : houston client registered ", hostname)
|
||||
|
||||
Outer:
|
||||
for {
|
||||
@ -198,6 +254,25 @@ Outer:
|
||||
return nil
|
||||
}
|
||||
|
||||
func (os *operationServer) ReportDeployingProgress(ctx context.Context, dp *protos.DeployingProgress) (*protos.Empty, error) {
|
||||
os.db.Lock()
|
||||
defer os.db.Unlock()
|
||||
|
||||
for i, p := range os.db.progs {
|
||||
if p.Hostname == dp.Hostname && p.Name == dp.Name && p.Version == dp.Version {
|
||||
os.db.progs[i].DeployingProgress = dp
|
||||
os.db.progs[i].Timestamp = time.Now().UTC().Unix()
|
||||
return &protos.Empty{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
os.db.progs = append(os.db.progs, deployingProgress{
|
||||
DeployingProgress: dp,
|
||||
Timestamp: time.Now().UTC().Unix(),
|
||||
})
|
||||
return &protos.Empty{}, nil
|
||||
}
|
||||
|
||||
func (os *operationServer) Refresh(ctx context.Context, desc *protos.OperationQueryRequest) (*protos.Empty, error) {
|
||||
os.hp.refresh(desc)
|
||||
return &protos.Empty{}, nil
|
||||
@ -227,12 +302,29 @@ func (os *operationServer) Deploy(d DeployRequest) {
|
||||
})
|
||||
}
|
||||
|
||||
for _, t := range targets {
|
||||
dps := make([]deployingProgress, len(targets))
|
||||
now := time.Now().UTC().Unix()
|
||||
for i, t := range targets {
|
||||
dps[i] = deployingProgress{
|
||||
DeployingProgress: &protos.DeployingProgress{
|
||||
Hostname: t.Hostname,
|
||||
Name: d.Name,
|
||||
Version: d.Version,
|
||||
State: "prepare",
|
||||
},
|
||||
Timestamp: now,
|
||||
}
|
||||
|
||||
t.opChan <- &opdef{
|
||||
operation: shared.Deploy,
|
||||
args: d,
|
||||
}
|
||||
}
|
||||
|
||||
os.db.Lock()
|
||||
defer os.db.Unlock()
|
||||
|
||||
os.db.progs = dps
|
||||
}
|
||||
|
||||
func (os *operationServer) Withdraw(d WithdrawRequest) {
|
||||
@ -341,26 +433,18 @@ func (os *operationServer) RestartProcess(d RestartProcessRequest) {
|
||||
return false
|
||||
})
|
||||
|
||||
if len(d.hostnames) > 0 {
|
||||
// hostname만 재시작
|
||||
var final []*hostWithChan
|
||||
conv := make(map[string]bool)
|
||||
for _, hn := range d.hostnames {
|
||||
conv[hn] = true
|
||||
}
|
||||
|
||||
for _, t := range targets {
|
||||
if _, ok := conv[t.Hostname]; ok {
|
||||
final = append(final, t)
|
||||
}
|
||||
}
|
||||
targets = final
|
||||
if len(d.hostnames) != 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// hostname만 재시작
|
||||
for _, t := range targets {
|
||||
t.opChan <- &opdef{
|
||||
operation: shared.Restart,
|
||||
args: d,
|
||||
if t.Hostname == d.hostnames[0] {
|
||||
t.opChan <- &opdef{
|
||||
operation: shared.Restart,
|
||||
args: d,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -400,10 +484,43 @@ func (os *operationServer) Hosts() map[string]hostSnapshot {
|
||||
return os.hp.allHosts()
|
||||
}
|
||||
|
||||
func (os *operationServer) DeplyingProgress() []deployingProgress {
|
||||
return os.db.clone()
|
||||
}
|
||||
|
||||
func targetExportLoop(in chan string) {
|
||||
all := make(map[string]bool)
|
||||
for addr := range in {
|
||||
logger.Println("targetExportLoop :", addr)
|
||||
if addr[0] == '+' {
|
||||
all[addr[1:]] = true
|
||||
} else if addr[0] == '-' {
|
||||
delete(all, addr[1:])
|
||||
}
|
||||
|
||||
list := make([]string, 0, len(all))
|
||||
for k := range all {
|
||||
list = append(list, k)
|
||||
}
|
||||
|
||||
output := []map[string]any{{"targets": list}}
|
||||
|
||||
if file, err := os.Create("prometheus_targets.json"); err == nil {
|
||||
enc := json.NewEncoder(file)
|
||||
enc.Encode(output)
|
||||
file.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newOperationServer() *operationServer {
|
||||
exportChan := make(chan string)
|
||||
go targetExportLoop(exportChan)
|
||||
|
||||
return &operationServer{
|
||||
hp: hostPool{
|
||||
hosts: map[string]*hostWithChan{},
|
||||
hosts: map[string]*hostWithChan{},
|
||||
exportChan: exportChan,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,9 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"repositories.action2quare.com/ayo/gocommon"
|
||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||
"repositories.action2quare.com/ayo/houston/shared"
|
||||
"repositories.action2quare.com/ayo/houston/shared/protos"
|
||||
|
||||
@ -12,11 +15,16 @@ import (
|
||||
|
||||
// protoc --go_out=. --go-grpc_out=. protos/*.proto
|
||||
type HoustonServer interface {
|
||||
Start(port int) error
|
||||
Start() error
|
||||
Stop()
|
||||
Operation() Operation
|
||||
}
|
||||
|
||||
type serverConfig struct {
|
||||
GrpcPort int `json:"grpc_port"`
|
||||
StorageRoot string `json:"storage_path"`
|
||||
}
|
||||
|
||||
type DeployRequest struct {
|
||||
shared.DeployRequest
|
||||
hostnames []string
|
||||
@ -97,10 +105,41 @@ type Operation interface {
|
||||
RestartProcess(RestartProcessRequest)
|
||||
Upload(UploadRequest)
|
||||
Hosts() map[string]hostSnapshot
|
||||
DeplyingProgress() []deployingProgress
|
||||
}
|
||||
|
||||
type outerconfig struct {
|
||||
Houston struct {
|
||||
Server serverConfig `json:"server"`
|
||||
} `json:"houston"`
|
||||
}
|
||||
|
||||
var storagePath = flagx.String("hs_storage", "", "")
|
||||
var grpcPort = flagx.Int("hs_grpc_port", 0, "")
|
||||
|
||||
func loadServerConfig() serverConfig {
|
||||
var oc outerconfig
|
||||
err := gocommon.LoadConfig[outerconfig](&oc)
|
||||
if err != nil {
|
||||
logger.Println(err)
|
||||
return serverConfig{
|
||||
GrpcPort: 8080,
|
||||
}
|
||||
}
|
||||
|
||||
if len(*storagePath) > 0 {
|
||||
// override
|
||||
oc.Houston.Server.StorageRoot = *storagePath
|
||||
}
|
||||
|
||||
if *grpcPort != 0 {
|
||||
oc.Houston.Server.GrpcPort = *grpcPort
|
||||
}
|
||||
|
||||
return oc.Houston.Server
|
||||
}
|
||||
|
||||
func NewServer() HoustonServer {
|
||||
|
||||
var opts []grpc.ServerOption
|
||||
grpcServer := grpc.NewServer(opts...)
|
||||
|
||||
@ -113,6 +152,7 @@ func NewServer() HoustonServer {
|
||||
rpcServer: grpcServer,
|
||||
os: os,
|
||||
ms: ms,
|
||||
port: loadServerConfig().GrpcPort,
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,23 +160,21 @@ type houstonServer struct {
|
||||
rpcServer *grpc.Server
|
||||
os *operationServer
|
||||
ms *monitorServer
|
||||
port int
|
||||
}
|
||||
|
||||
func (hs *houstonServer) Start(port int) error {
|
||||
lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
|
||||
func (hs *houstonServer) Start() error {
|
||||
logger.Println("houston server is started at port", hs.port)
|
||||
lis, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", hs.port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := hs.rpcServer.Serve(lis); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return hs.rpcServer.Serve(lis)
|
||||
}
|
||||
|
||||
func (hs *houstonServer) Stop() {
|
||||
hs.rpcServer.GracefulStop()
|
||||
hs.rpcServer.Stop()
|
||||
}
|
||||
|
||||
func (hs *houstonServer) Operation() Operation {
|
||||
|
||||
@ -1,27 +1,23 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Operation string
|
||||
|
||||
const (
|
||||
Deploy = Operation("deploy")
|
||||
Withdraw = Operation("withdraw")
|
||||
Upgrade = Operation("upgrade")
|
||||
Start = Operation("start")
|
||||
Restart = Operation("restart")
|
||||
Stop = Operation("stop")
|
||||
Upload = Operation("upload")
|
||||
Deploy = Operation("deploy")
|
||||
Withdraw = Operation("withdraw")
|
||||
Upgrade = Operation("upgrade")
|
||||
Start = Operation("start")
|
||||
Restart = Operation("restart")
|
||||
Stop = Operation("stop")
|
||||
Upload = Operation("upload")
|
||||
Exception = Operation("exception")
|
||||
)
|
||||
|
||||
type DeployRequest struct {
|
||||
Name string
|
||||
Version string
|
||||
Url string
|
||||
Config string
|
||||
AccessToken string
|
||||
}
|
||||
|
||||
@ -31,9 +27,11 @@ type WithdrawRequest struct {
|
||||
}
|
||||
|
||||
type StartProcessRequest struct {
|
||||
Name string
|
||||
Version string
|
||||
Args string
|
||||
Name string
|
||||
Version string
|
||||
Args []string
|
||||
AutoRestart bool
|
||||
OutputLogFile string
|
||||
}
|
||||
|
||||
type StopProcessRequest struct {
|
||||
@ -43,8 +41,9 @@ type StopProcessRequest struct {
|
||||
}
|
||||
|
||||
type RestartProcessRequest struct {
|
||||
Name string
|
||||
Version string
|
||||
Name string
|
||||
Pid int32
|
||||
Config string
|
||||
}
|
||||
|
||||
type UploadRequest struct {
|
||||
@ -54,61 +53,3 @@ type UploadRequest struct {
|
||||
Filter string
|
||||
DeleteAfterUploaded string // true, false
|
||||
}
|
||||
|
||||
type ParsedVersionString = []string
|
||||
|
||||
func ParseVersionString(ver string) ParsedVersionString {
|
||||
return strings.Split(ver, ".")
|
||||
}
|
||||
|
||||
func CompareVersionString(lhs, rhs ParsedVersionString) int {
|
||||
minlen := len(lhs)
|
||||
if minlen > len(rhs) {
|
||||
minlen = len(rhs)
|
||||
}
|
||||
|
||||
for i := 0; i < minlen; i++ {
|
||||
if len(lhs[i]) < len(rhs[i]) {
|
||||
return -1
|
||||
}
|
||||
|
||||
if len(lhs[i]) > len(rhs[i]) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if lhs[i] < rhs[i] {
|
||||
return -1
|
||||
}
|
||||
|
||||
if lhs[i] > rhs[i] {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
return len(lhs) - len(rhs)
|
||||
}
|
||||
|
||||
func FindLastestVersion(root string) (string, error) {
|
||||
// 최신 버전을 찾음
|
||||
entries, err := os.ReadDir(root)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
var dironly []fs.DirEntry
|
||||
for _, ent := range entries {
|
||||
if ent.IsDir() {
|
||||
dironly = append(dironly, ent)
|
||||
}
|
||||
}
|
||||
latest := ParseVersionString(dironly[0].Name())
|
||||
for i := 1; i < len(dironly); i++ {
|
||||
next := ParseVersionString(dironly[i].Name())
|
||||
if CompareVersionString(latest, next) < 0 {
|
||||
latest = next
|
||||
}
|
||||
}
|
||||
return strings.Join(latest, "."), nil
|
||||
}
|
||||
|
||||
@ -26,7 +26,8 @@ const (
|
||||
ProcessState_Stopped ProcessState = 0
|
||||
ProcessState_Stopping ProcessState = 1
|
||||
ProcessState_Running ProcessState = 2
|
||||
ProcessState_Error ProcessState = 3
|
||||
ProcessState_Restart ProcessState = 3
|
||||
ProcessState_Error ProcessState = 4
|
||||
)
|
||||
|
||||
// Enum value maps for ProcessState.
|
||||
@ -35,13 +36,15 @@ var (
|
||||
0: "Stopped",
|
||||
1: "Stopping",
|
||||
2: "Running",
|
||||
3: "Error",
|
||||
3: "Restart",
|
||||
4: "Error",
|
||||
}
|
||||
ProcessState_value = map[string]int32{
|
||||
"Stopped": 0,
|
||||
"Stopping": 1,
|
||||
"Running": 2,
|
||||
"Error": 3,
|
||||
"Restart": 3,
|
||||
"Error": 4,
|
||||
}
|
||||
)
|
||||
|
||||
@ -187,9 +190,11 @@ type OperationQueryRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||
Procs []*ProcessDescription `protobuf:"bytes,2,rep,name=procs,proto3" json:"procs,omitempty"`
|
||||
Deploys []*DeployedVersions `protobuf:"bytes,3,rep,name=deploys,proto3" json:"deploys,omitempty"`
|
||||
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||
PublicIp string `protobuf:"bytes,4,opt,name=public_ip,json=publicIp,proto3" json:"public_ip,omitempty"`
|
||||
PrivateIp string `protobuf:"bytes,5,opt,name=private_ip,json=privateIp,proto3" json:"private_ip,omitempty"`
|
||||
Procs []*ProcessDescription `protobuf:"bytes,2,rep,name=procs,proto3" json:"procs,omitempty"`
|
||||
Deploys []*DeployedVersions `protobuf:"bytes,3,rep,name=deploys,proto3" json:"deploys,omitempty"`
|
||||
}
|
||||
|
||||
func (x *OperationQueryRequest) Reset() {
|
||||
@ -231,6 +236,20 @@ func (x *OperationQueryRequest) GetHostname() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *OperationQueryRequest) GetPublicIp() string {
|
||||
if x != nil {
|
||||
return x.PublicIp
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *OperationQueryRequest) GetPrivateIp() string {
|
||||
if x != nil {
|
||||
return x.PrivateIp
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *OperationQueryRequest) GetProcs() []*ProcessDescription {
|
||||
if x != nil {
|
||||
return x.Procs
|
||||
@ -250,13 +269,11 @@ type ProcessDescription struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Args []string `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"`
|
||||
Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`
|
||||
State ProcessState `protobuf:"varint,4,opt,name=state,proto3,enum=ProcessState" json:"state,omitempty"`
|
||||
Pid int32 `protobuf:"varint,5,opt,name=pid,proto3" json:"pid,omitempty"`
|
||||
StdoutSize int32 `protobuf:"varint,6,opt,name=stdout_size,json=stdoutSize,proto3" json:"stdout_size,omitempty"`
|
||||
StderrSize int32 `protobuf:"varint,7,opt,name=stderr_size,json=stderrSize,proto3" json:"stderr_size,omitempty"`
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Args []string `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"`
|
||||
Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`
|
||||
State ProcessState `protobuf:"varint,4,opt,name=state,proto3,enum=ProcessState" json:"state,omitempty"`
|
||||
Pid int32 `protobuf:"varint,5,opt,name=pid,proto3" json:"pid,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ProcessDescription) Reset() {
|
||||
@ -326,20 +343,6 @@ func (x *ProcessDescription) GetPid() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ProcessDescription) GetStdoutSize() int32 {
|
||||
if x != nil {
|
||||
return x.StdoutSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ProcessDescription) GetStderrSize() int32 {
|
||||
if x != nil {
|
||||
return x.StderrSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type OperationQueryResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -395,6 +398,93 @@ func (x *OperationQueryResponse) GetArgs() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeployingProgress struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`
|
||||
State string `protobuf:"bytes,4,opt,name=state,proto3" json:"state,omitempty"`
|
||||
Progress int64 `protobuf:"varint,5,opt,name=progress,proto3" json:"progress,omitempty"`
|
||||
Total int64 `protobuf:"varint,6,opt,name=total,proto3" json:"total,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) Reset() {
|
||||
*x = DeployingProgress{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_protos_operation_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeployingProgress) ProtoMessage() {}
|
||||
|
||||
func (x *DeployingProgress) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protos_operation_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeployingProgress.ProtoReflect.Descriptor instead.
|
||||
func (*DeployingProgress) Descriptor() ([]byte, []int) {
|
||||
return file_protos_operation_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) GetHostname() string {
|
||||
if x != nil {
|
||||
return x.Hostname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) GetVersion() string {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) GetState() string {
|
||||
if x != nil {
|
||||
return x.State
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) GetProgress() int64 {
|
||||
if x != nil {
|
||||
return x.Progress
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DeployingProgress) GetTotal() int64 {
|
||||
if x != nil {
|
||||
return x.Total
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_protos_operation_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_protos_operation_proto_rawDesc = []byte{
|
||||
@ -410,43 +500,54 @@ var file_protos_operation_proto_rawDesc = []byte{
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x41, 0x6e, 0x64, 0x41, 0x72, 0x67, 0x73, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x22, 0x8b, 0x01, 0x0a, 0x15, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51,
|
||||
0x73, 0x22, 0xc7, 0x01, 0x0a, 0x15, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51,
|
||||
0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x68,
|
||||
0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68,
|
||||
0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x63, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
|
||||
0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x70, 0x72, 0x6f,
|
||||
0x63, 0x73, 0x12, 0x2b, 0x0a, 0x07, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x73, 0x18, 0x03, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x56, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x73, 0x22,
|
||||
0xcf, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72,
|
||||
0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
|
||||
0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x70, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12,
|
||||
0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x53, 0x69, 0x7a, 0x65,
|
||||
0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x22, 0xa6, 0x01, 0x0a, 0x16, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51,
|
||||
0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09,
|
||||
0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x04, 0x61, 0x72,
|
||||
0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x2e, 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x61, 0x72, 0x67,
|
||||
0x73, 0x1a, 0x37, 0x0a, 0x09, 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x2a, 0x41, 0x0a, 0x0c, 0x50, 0x72,
|
||||
0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x74,
|
||||
0x6f, 0x70, 0x70, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x74, 0x6f, 0x70, 0x70,
|
||||
0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67,
|
||||
0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x03, 0x32, 0x78, 0x0a,
|
||||
0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x5f, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x49, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f,
|
||||
0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,
|
||||
0x65, 0x49, 0x70, 0x12, 0x29, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x44, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x63, 0x73, 0x12, 0x2b,
|
||||
0x0a, 0x07, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x11, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x52, 0x07, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x12,
|
||||
0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02,
|
||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61,
|
||||
0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0xa6, 0x01, 0x0a, 0x16,
|
||||
0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75,
|
||||
0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x72, 0x67, 0x73,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x41,
|
||||
0x72, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x22, 0xa5, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x69,
|
||||
0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f,
|
||||
0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f,
|
||||
0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72,
|
||||
0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x72,
|
||||
0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x2a, 0x4e, 0x0a, 0x0c,
|
||||
0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07,
|
||||
0x53, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x74, 0x6f,
|
||||
0x70, 0x70, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x6e, 0x69,
|
||||
0x6e, 0x67, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x10,
|
||||
0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x04, 0x32, 0xb1, 0x01, 0x0a,
|
||||
0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x05, 0x51, 0x75,
|
||||
0x65, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51,
|
||||
0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x4f, 0x70,
|
||||
@ -454,8 +555,12 @@ var file_protos_operation_proto_rawDesc = []byte{
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x2b, 0x0a, 0x07, 0x52, 0x65,
|
||||
0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x16, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x06, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x0f, 0x5a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||
0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x17, 0x52, 0x65, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65,
|
||||
0x73, 0x73, 0x12, 0x12, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72,
|
||||
0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x06, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00,
|
||||
0x42, 0x0f, 0x5a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -471,7 +576,7 @@ func file_protos_operation_proto_rawDescGZIP() []byte {
|
||||
}
|
||||
|
||||
var file_protos_operation_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_protos_operation_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_protos_operation_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_protos_operation_proto_goTypes = []interface{}{
|
||||
(ProcessState)(0), // 0: ProcessState
|
||||
(*VersionAndArgs)(nil), // 1: VersionAndArgs
|
||||
@ -479,21 +584,24 @@ var file_protos_operation_proto_goTypes = []interface{}{
|
||||
(*OperationQueryRequest)(nil), // 3: OperationQueryRequest
|
||||
(*ProcessDescription)(nil), // 4: ProcessDescription
|
||||
(*OperationQueryResponse)(nil), // 5: OperationQueryResponse
|
||||
nil, // 6: OperationQueryResponse.ArgsEntry
|
||||
(*Empty)(nil), // 7: Empty
|
||||
(*DeployingProgress)(nil), // 6: DeployingProgress
|
||||
nil, // 7: OperationQueryResponse.ArgsEntry
|
||||
(*Empty)(nil), // 8: Empty
|
||||
}
|
||||
var file_protos_operation_proto_depIdxs = []int32{
|
||||
1, // 0: DeployedVersions.versions:type_name -> VersionAndArgs
|
||||
4, // 1: OperationQueryRequest.procs:type_name -> ProcessDescription
|
||||
2, // 2: OperationQueryRequest.deploys:type_name -> DeployedVersions
|
||||
0, // 3: ProcessDescription.state:type_name -> ProcessState
|
||||
6, // 4: OperationQueryResponse.args:type_name -> OperationQueryResponse.ArgsEntry
|
||||
7, // 4: OperationQueryResponse.args:type_name -> OperationQueryResponse.ArgsEntry
|
||||
3, // 5: Operation.Query:input_type -> OperationQueryRequest
|
||||
3, // 6: Operation.Refresh:input_type -> OperationQueryRequest
|
||||
5, // 7: Operation.Query:output_type -> OperationQueryResponse
|
||||
7, // 8: Operation.Refresh:output_type -> Empty
|
||||
7, // [7:9] is the sub-list for method output_type
|
||||
5, // [5:7] is the sub-list for method input_type
|
||||
6, // 7: Operation.ReportDeployingProgress:input_type -> DeployingProgress
|
||||
5, // 8: Operation.Query:output_type -> OperationQueryResponse
|
||||
8, // 9: Operation.Refresh:output_type -> Empty
|
||||
8, // 10: Operation.ReportDeployingProgress:output_type -> Empty
|
||||
8, // [8:11] is the sub-list for method output_type
|
||||
5, // [5:8] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
@ -566,6 +674,18 @@ func file_protos_operation_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_protos_operation_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DeployingProgress); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@ -573,7 +693,7 @@ func file_protos_operation_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_protos_operation_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 6,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@ -24,6 +24,7 @@ const _ = grpc.SupportPackageIsVersion7
|
||||
type OperationClient interface {
|
||||
Query(ctx context.Context, opts ...grpc.CallOption) (Operation_QueryClient, error)
|
||||
Refresh(ctx context.Context, in *OperationQueryRequest, opts ...grpc.CallOption) (*Empty, error)
|
||||
ReportDeployingProgress(ctx context.Context, in *DeployingProgress, opts ...grpc.CallOption) (*Empty, error)
|
||||
}
|
||||
|
||||
type operationClient struct {
|
||||
@ -74,12 +75,22 @@ func (c *operationClient) Refresh(ctx context.Context, in *OperationQueryRequest
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *operationClient) ReportDeployingProgress(ctx context.Context, in *DeployingProgress, opts ...grpc.CallOption) (*Empty, error) {
|
||||
out := new(Empty)
|
||||
err := c.cc.Invoke(ctx, "/Operation/ReportDeployingProgress", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// OperationServer is the server API for Operation service.
|
||||
// All implementations must embed UnimplementedOperationServer
|
||||
// for forward compatibility
|
||||
type OperationServer interface {
|
||||
Query(Operation_QueryServer) error
|
||||
Refresh(context.Context, *OperationQueryRequest) (*Empty, error)
|
||||
ReportDeployingProgress(context.Context, *DeployingProgress) (*Empty, error)
|
||||
mustEmbedUnimplementedOperationServer()
|
||||
}
|
||||
|
||||
@ -93,6 +104,9 @@ func (UnimplementedOperationServer) Query(Operation_QueryServer) error {
|
||||
func (UnimplementedOperationServer) Refresh(context.Context, *OperationQueryRequest) (*Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Refresh not implemented")
|
||||
}
|
||||
func (UnimplementedOperationServer) ReportDeployingProgress(context.Context, *DeployingProgress) (*Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReportDeployingProgress not implemented")
|
||||
}
|
||||
func (UnimplementedOperationServer) mustEmbedUnimplementedOperationServer() {}
|
||||
|
||||
// UnsafeOperationServer may be embedded to opt out of forward compatibility for this service.
|
||||
@ -150,6 +164,24 @@ func _Operation_Refresh_Handler(srv interface{}, ctx context.Context, dec func(i
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Operation_ReportDeployingProgress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeployingProgress)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(OperationServer).ReportDeployingProgress(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Operation/ReportDeployingProgress",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(OperationServer).ReportDeployingProgress(ctx, req.(*DeployingProgress))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Operation_ServiceDesc is the grpc.ServiceDesc for Operation service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@ -161,6 +193,10 @@ var Operation_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Refresh",
|
||||
Handler: _Operation_Refresh_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ReportDeployingProgress",
|
||||
Handler: _Operation_ReportDeployingProgress_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user