mirror of
https://github.com/OliveTin/OliveTin
synced 2025-12-12 00:55:34 +00:00
feature: Execute actions on startup. Externalize the executor and add… (#101)
* feature: Execute actions on startup. Externalize the executor and add tags to logs. * fmt: Codestyle fixes
This commit is contained in:
@@ -70,6 +70,7 @@ message LogEntry {
|
||||
string user = 7;
|
||||
string userClass = 8;
|
||||
string actionIcon = 9;
|
||||
repeated string tags = 10;
|
||||
}
|
||||
|
||||
message GetLogsResponse {
|
||||
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/OliveTin/OliveTin/internal/executor"
|
||||
grpcapi "github.com/OliveTin/OliveTin/internal/grpcapi"
|
||||
"github.com/OliveTin/OliveTin/internal/onstartup"
|
||||
updatecheck "github.com/OliveTin/OliveTin/internal/updatecheck"
|
||||
|
||||
"github.com/OliveTin/OliveTin/internal/httpservers"
|
||||
@@ -100,9 +102,13 @@ func main() {
|
||||
|
||||
log.Debugf("Config: %+v", cfg)
|
||||
|
||||
executor := executor.DefaultExecutor()
|
||||
|
||||
go onstartup.Execute(cfg, executor)
|
||||
|
||||
go updatecheck.StartUpdateChecker(version, commit, cfg, configDir)
|
||||
|
||||
go grpcapi.Start(cfg)
|
||||
go grpcapi.Start(cfg, executor)
|
||||
|
||||
httpservers.StartServers(cfg)
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@ package config
|
||||
// Action represents the core functionality of OliveTin - commands that show up
|
||||
// as buttons in the UI.
|
||||
type Action struct {
|
||||
ID string
|
||||
Title string
|
||||
Icon string
|
||||
Shell string
|
||||
CSS map[string]string `mapstructure:"omitempty"`
|
||||
Timeout int
|
||||
Acls []string
|
||||
Arguments []ActionArgument
|
||||
ID string
|
||||
Title string
|
||||
Icon string
|
||||
Shell string
|
||||
CSS map[string]string `mapstructure:"omitempty"`
|
||||
Timeout int
|
||||
Acls []string
|
||||
ExecOnStartup bool
|
||||
Arguments []ActionArgument
|
||||
}
|
||||
|
||||
// ActionArgument objects appear on Actions.
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
type ExecutionRequest struct {
|
||||
ActionName string
|
||||
Arguments map[string]string
|
||||
Tags []string
|
||||
action *config.Action
|
||||
Cfg *config.Config
|
||||
AuthenticatedUser *acl.AuthenticatedUser
|
||||
@@ -33,6 +34,7 @@ type InternalLogEntry struct {
|
||||
Stderr string
|
||||
TimedOut bool
|
||||
ExitCode int32
|
||||
Tags []string
|
||||
|
||||
/*
|
||||
The following two properties are obviously on Action normally, but it's useful
|
||||
@@ -185,5 +187,7 @@ func stepExec(req *ExecutionRequest) bool {
|
||||
req.logEntry.TimedOut = true
|
||||
}
|
||||
|
||||
req.logEntry.Tags = req.Tags
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -15,11 +15,12 @@ import (
|
||||
|
||||
var (
|
||||
cfg *config.Config
|
||||
ex = executor.DefaultExecutor()
|
||||
)
|
||||
|
||||
type oliveTinAPI struct {
|
||||
pb.UnimplementedOliveTinApiServer
|
||||
|
||||
executor *executor.Executor
|
||||
}
|
||||
|
||||
func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest) (*pb.StartActionResponse, error) {
|
||||
@@ -38,7 +39,7 @@ func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest)
|
||||
Cfg: cfg,
|
||||
}
|
||||
|
||||
return ex.ExecRequest(&execReq), nil
|
||||
return api.executor.ExecRequest(&execReq), nil
|
||||
}
|
||||
|
||||
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) {
|
||||
@@ -60,7 +61,7 @@ func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *pb.GetLogsRequest) (*pb.Ge
|
||||
|
||||
// TODO Limit to 10 entries or something to prevent browser lag.
|
||||
|
||||
for _, logEntry := range ex.Logs {
|
||||
for _, logEntry := range api.executor.Logs {
|
||||
ret.Logs = append(ret.Logs, &pb.LogEntry{
|
||||
ActionTitle: logEntry.ActionTitle,
|
||||
ActionIcon: logEntry.ActionIcon,
|
||||
@@ -69,6 +70,7 @@ func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *pb.GetLogsRequest) (*pb.Ge
|
||||
Stderr: logEntry.Stderr,
|
||||
TimedOut: logEntry.TimedOut,
|
||||
ExitCode: logEntry.ExitCode,
|
||||
Tags: logEntry.Tags,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -107,7 +109,7 @@ func (api *oliveTinAPI) WhoAmI(ctx ctx.Context, req *pb.WhoAmIRequest) (*pb.WhoA
|
||||
}
|
||||
|
||||
// Start will start the GRPC API.
|
||||
func Start(globalConfig *config.Config) {
|
||||
func Start(globalConfig *config.Config, ex *executor.Executor) {
|
||||
cfg = globalConfig
|
||||
|
||||
lis, err := net.Listen("tcp", cfg.ListenAddressGrpcActions)
|
||||
@@ -117,7 +119,7 @@ func Start(globalConfig *config.Config) {
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer()
|
||||
pb.RegisterOliveTinApiServer(grpcServer, newServer())
|
||||
pb.RegisterOliveTinApiServer(grpcServer, newServer(ex))
|
||||
|
||||
err = grpcServer.Serve(lis)
|
||||
|
||||
@@ -126,7 +128,8 @@ func Start(globalConfig *config.Config) {
|
||||
}
|
||||
}
|
||||
|
||||
func newServer() *oliveTinAPI {
|
||||
func newServer(ex *executor.Executor) *oliveTinAPI {
|
||||
server := oliveTinAPI{}
|
||||
server.executor = ex
|
||||
return &server
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
pb "github.com/OliveTin/OliveTin/gen/grpc"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
"github.com/OliveTin/OliveTin/internal/executor"
|
||||
)
|
||||
|
||||
const bufSize = 1024 * 1024
|
||||
@@ -21,9 +22,11 @@ const bufSize = 1024 * 1024
|
||||
var lis *bufconn.Listener
|
||||
|
||||
func init() {
|
||||
ex := executor.DefaultExecutor()
|
||||
|
||||
lis = bufconn.Listen(bufSize)
|
||||
s := grpc.NewServer()
|
||||
pb.RegisterOliveTinApiServer(s, newServer())
|
||||
pb.RegisterOliveTinApiServer(s, newServer(ex))
|
||||
|
||||
go func() {
|
||||
if err := s.Serve(lis); err != nil {
|
||||
|
||||
32
internal/onstartup/startup.go
Normal file
32
internal/onstartup/startup.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package onstartup
|
||||
|
||||
import (
|
||||
"github.com/OliveTin/OliveTin/internal/acl"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
"github.com/OliveTin/OliveTin/internal/executor"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func Execute(cfg *config.Config, ex *executor.Executor) {
|
||||
user := &acl.AuthenticatedUser{
|
||||
Username: "startup-user",
|
||||
}
|
||||
|
||||
for _, action := range cfg.Actions {
|
||||
if action.ExecOnStartup {
|
||||
log.WithFields(log.Fields{
|
||||
"action": action.Title,
|
||||
}).Infof("Startup action")
|
||||
|
||||
req := &executor.ExecutionRequest{
|
||||
ActionName: action.Title,
|
||||
Arguments: nil,
|
||||
Cfg: cfg,
|
||||
Tags: []string{"startup"},
|
||||
AuthenticatedUser: user,
|
||||
}
|
||||
|
||||
ex.ExecRequest(req)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@
|
||||
<td>
|
||||
<span class = "icon" role = "icon"></span>
|
||||
<span class = "content">?</span>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>stdout</summary>
|
||||
<pre class = "stdout">
|
||||
@@ -117,6 +117,7 @@
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
<div class = "tags"></div>
|
||||
</td>
|
||||
<td class = "exit-code">?</td>
|
||||
</tr>
|
||||
|
||||
@@ -57,6 +57,14 @@ export function marshalLogsJsonToHtml (json) {
|
||||
row.querySelector('pre.stderr').innerText = logEntry.stderr
|
||||
row.querySelector('.exit-code').innerText = logTableExitCode
|
||||
|
||||
for (const tag of logEntry.tags) {
|
||||
const domTag = document.createElement('span')
|
||||
domTag.classList.add('tag')
|
||||
domTag.innerText = tag
|
||||
|
||||
row.querySelector('.tags').append(domTag)
|
||||
}
|
||||
|
||||
document.querySelector('#logTableBody').prepend(row)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +387,12 @@ input.invalid {
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
span.tag {
|
||||
background-color: lightgray;
|
||||
border-radius: 0.6em;
|
||||
padding: 0.2em;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #333;
|
||||
|
||||
Reference in New Issue
Block a user