mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-08-07 15:26:26 +00:00
ecad6514f3
* new agent structure Signed-off-by: Sammy Oina <sammyoina@gmail.com> * minor fixes and testing Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix lint Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix tests Signed-off-by: Sammy Oina <sammyoina@gmail.com> * cvm tests fix Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix test Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix cli test Signed-off-by: Sammy Oina <sammyoina@gmail.com> * rename Signed-off-by: Sammy Oina <sammyoina@gmail.com> * rename cvm to cvms plural Signed-off-by: Sammy Oina <sammyoina@gmail.com> * rename service Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix tests Signed-off-by: Sammy Oina <sammyoina@gmail.com> * remove context Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: reorder parameters in NewAlgorithm functions and update CVMClient to CVMSClient Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix(tests): update SendEvent mock to include an additional parameter Signed-off-by: Sammy Oina <sammyoina@gmail.com> * move expectations Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix(tests): move event initialization to the correct scope in service tests Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix(tests): update SendEvent mock to use EXPECT instead of On in service tests Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com>
123 lines
3.0 KiB
Go
123 lines
3.0 KiB
Go
// Copyright (c) Ultraviolet
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
package python
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
|
|
"github.com/ultravioletrs/cocos/agent/algorithm"
|
|
"github.com/ultravioletrs/cocos/agent/algorithm/logging"
|
|
"github.com/ultravioletrs/cocos/agent/events"
|
|
"google.golang.org/grpc/metadata"
|
|
)
|
|
|
|
const (
|
|
PyRuntime = "python3"
|
|
PyRuntimeKey = "python_runtime"
|
|
)
|
|
|
|
func PythonRunTimeToContext(ctx context.Context, runtime string) context.Context {
|
|
return metadata.AppendToOutgoingContext(ctx, PyRuntimeKey, runtime)
|
|
}
|
|
|
|
func PythonRunTimeFromContext(ctx context.Context) string {
|
|
return metadata.ValueFromIncomingContext(ctx, PyRuntimeKey)[0]
|
|
}
|
|
|
|
var _ algorithm.Algorithm = (*python)(nil)
|
|
|
|
type python struct {
|
|
algoFile string
|
|
stderr io.Writer
|
|
stdout io.Writer
|
|
runtime string
|
|
requirementsFile string
|
|
args []string
|
|
cmd *exec.Cmd
|
|
}
|
|
|
|
func NewAlgorithm(logger *slog.Logger, eventsSvc events.Service, runtime, requirementsFile, algoFile string, args []string, cmpID string) algorithm.Algorithm {
|
|
p := &python{
|
|
algoFile: algoFile,
|
|
stderr: &logging.Stderr{Logger: logger, EventSvc: eventsSvc, CmpID: cmpID},
|
|
stdout: &logging.Stdout{Logger: logger},
|
|
requirementsFile: requirementsFile,
|
|
args: args,
|
|
}
|
|
if runtime != "" {
|
|
p.runtime = runtime
|
|
} else {
|
|
p.runtime = PyRuntime
|
|
}
|
|
return p
|
|
}
|
|
|
|
func (p *python) Run() error {
|
|
venvPath := "venv"
|
|
createVenvCmd := exec.Command(p.runtime, "-m", "venv", venvPath)
|
|
createVenvCmd.Stderr = p.stderr
|
|
createVenvCmd.Stdout = p.stdout
|
|
if err := createVenvCmd.Run(); err != nil {
|
|
return fmt.Errorf("error creating virtual environment: %v", err)
|
|
}
|
|
|
|
pythonPath := filepath.Join(venvPath, "bin", "python")
|
|
|
|
updatePipCmd := exec.Command(pythonPath, "-m", "pip", "install", "--upgrade", "pip")
|
|
updatePipCmd.Stderr = p.stderr
|
|
updatePipCmd.Stdout = p.stdout
|
|
if err := updatePipCmd.Run(); err != nil {
|
|
return fmt.Errorf("error updating pip: %v", err)
|
|
}
|
|
|
|
if p.requirementsFile != "" {
|
|
rcmd := exec.Command(pythonPath, "-m", "pip", "install", "-r", p.requirementsFile)
|
|
rcmd.Stderr = p.stderr
|
|
rcmd.Stdout = p.stdout
|
|
if err := rcmd.Run(); err != nil {
|
|
return fmt.Errorf("error installing requirements: %v", err)
|
|
}
|
|
}
|
|
|
|
args := append([]string{p.algoFile}, p.args...)
|
|
p.cmd = exec.Command(pythonPath, args...)
|
|
p.cmd.Stderr = p.stderr
|
|
p.cmd.Stdout = p.stdout
|
|
|
|
if err := p.cmd.Start(); err != nil {
|
|
return fmt.Errorf("error starting algorithm: %v", err)
|
|
}
|
|
|
|
if err := p.cmd.Wait(); err != nil {
|
|
return fmt.Errorf("algorithm execution error: %v", err)
|
|
}
|
|
|
|
if err := os.RemoveAll(venvPath); err != nil {
|
|
return fmt.Errorf("error removing virtual environment: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *python) Stop() error {
|
|
if p.cmd == nil {
|
|
return nil
|
|
}
|
|
|
|
if p.cmd.ProcessState != nil && p.cmd.ProcessState.Exited() {
|
|
return nil
|
|
}
|
|
|
|
if err := p.cmd.Process.Kill(); err != nil {
|
|
return fmt.Errorf("error stopping algorithm: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|