chore: wip OliveTin3k

This commit is contained in:
jamesread 2025-10-23 23:16:39 +01:00
parent 6836062b00
commit cbb163726e
13 changed files with 6095 additions and 80 deletions

2
.gitignore vendored
View File

@ -14,3 +14,5 @@ custom-frontend
integration-tests/screenshots/
.vscode/
webui/
server.log
OliveTin

View File

@ -21,13 +21,11 @@
</head>
<body>
<main title = "main content">
<slot id = "app" />
<slot id = "app" />
<noscript>
<div class = "error">Sorry, JavaScript is required to use OliveTin.</div>
</noscript>
</main>
<noscript>
<div class = "error">Sorry, JavaScript is required to use OliveTin.</div>
</noscript>
<dialog title = "Big Error Message" id = "big-error" class = "error padded-content">

3765
gen/grpc/OliveTin.pb.go Normal file

File diff suppressed because it is too large Load Diff

1383
gen/grpc/OliveTin.pb.gw.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,700 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc (unknown)
// source: OliveTin.proto
package grpc
import (
context "context"
httpbody "google.golang.org/genproto/googleapis/api/httpbody"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
OliveTinApiService_GetDashboardComponents_FullMethodName = "/OliveTinApiService/GetDashboardComponents"
OliveTinApiService_StartAction_FullMethodName = "/OliveTinApiService/StartAction"
OliveTinApiService_StartActionAndWait_FullMethodName = "/OliveTinApiService/StartActionAndWait"
OliveTinApiService_StartActionByGet_FullMethodName = "/OliveTinApiService/StartActionByGet"
OliveTinApiService_StartActionByGetAndWait_FullMethodName = "/OliveTinApiService/StartActionByGetAndWait"
OliveTinApiService_KillAction_FullMethodName = "/OliveTinApiService/KillAction"
OliveTinApiService_ExecutionStatus_FullMethodName = "/OliveTinApiService/ExecutionStatus"
OliveTinApiService_GetLogs_FullMethodName = "/OliveTinApiService/GetLogs"
OliveTinApiService_ValidateArgumentType_FullMethodName = "/OliveTinApiService/ValidateArgumentType"
OliveTinApiService_WhoAmI_FullMethodName = "/OliveTinApiService/WhoAmI"
OliveTinApiService_SosReport_FullMethodName = "/OliveTinApiService/SosReport"
OliveTinApiService_DumpVars_FullMethodName = "/OliveTinApiService/DumpVars"
OliveTinApiService_DumpPublicIdActionMap_FullMethodName = "/OliveTinApiService/DumpPublicIdActionMap"
OliveTinApiService_GetReadyz_FullMethodName = "/OliveTinApiService/GetReadyz"
OliveTinApiService_LocalUserLogin_FullMethodName = "/OliveTinApiService/LocalUserLogin"
OliveTinApiService_PasswordHash_FullMethodName = "/OliveTinApiService/PasswordHash"
OliveTinApiService_Logout_FullMethodName = "/OliveTinApiService/Logout"
)
// OliveTinApiServiceClient is the client API for OliveTinApiService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type OliveTinApiServiceClient interface {
GetDashboardComponents(ctx context.Context, in *GetDashboardComponentsRequest, opts ...grpc.CallOption) (*GetDashboardComponentsResponse, error)
StartAction(ctx context.Context, in *StartActionRequest, opts ...grpc.CallOption) (*StartActionResponse, error)
StartActionAndWait(ctx context.Context, in *StartActionAndWaitRequest, opts ...grpc.CallOption) (*StartActionAndWaitResponse, error)
StartActionByGet(ctx context.Context, in *StartActionByGetRequest, opts ...grpc.CallOption) (*StartActionByGetResponse, error)
StartActionByGetAndWait(ctx context.Context, in *StartActionByGetAndWaitRequest, opts ...grpc.CallOption) (*StartActionByGetAndWaitResponse, error)
KillAction(ctx context.Context, in *KillActionRequest, opts ...grpc.CallOption) (*KillActionResponse, error)
ExecutionStatus(ctx context.Context, in *ExecutionStatusRequest, opts ...grpc.CallOption) (*ExecutionStatusResponse, error)
GetLogs(ctx context.Context, in *GetLogsRequest, opts ...grpc.CallOption) (*GetLogsResponse, error)
ValidateArgumentType(ctx context.Context, in *ValidateArgumentTypeRequest, opts ...grpc.CallOption) (*ValidateArgumentTypeResponse, error)
WhoAmI(ctx context.Context, in *WhoAmIRequest, opts ...grpc.CallOption) (*WhoAmIResponse, error)
SosReport(ctx context.Context, in *SosReportRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error)
DumpVars(ctx context.Context, in *DumpVarsRequest, opts ...grpc.CallOption) (*DumpVarsResponse, error)
DumpPublicIdActionMap(ctx context.Context, in *DumpPublicIdActionMapRequest, opts ...grpc.CallOption) (*DumpPublicIdActionMapResponse, error)
GetReadyz(ctx context.Context, in *GetReadyzRequest, opts ...grpc.CallOption) (*GetReadyzResponse, error)
LocalUserLogin(ctx context.Context, in *LocalUserLoginRequest, opts ...grpc.CallOption) (*LocalUserLoginResponse, error)
PasswordHash(ctx context.Context, in *PasswordHashRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error)
Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error)
}
type oliveTinApiServiceClient struct {
cc grpc.ClientConnInterface
}
func NewOliveTinApiServiceClient(cc grpc.ClientConnInterface) OliveTinApiServiceClient {
return &oliveTinApiServiceClient{cc}
}
func (c *oliveTinApiServiceClient) GetDashboardComponents(ctx context.Context, in *GetDashboardComponentsRequest, opts ...grpc.CallOption) (*GetDashboardComponentsResponse, error) {
out := new(GetDashboardComponentsResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_GetDashboardComponents_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) StartAction(ctx context.Context, in *StartActionRequest, opts ...grpc.CallOption) (*StartActionResponse, error) {
out := new(StartActionResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_StartAction_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) StartActionAndWait(ctx context.Context, in *StartActionAndWaitRequest, opts ...grpc.CallOption) (*StartActionAndWaitResponse, error) {
out := new(StartActionAndWaitResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_StartActionAndWait_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) StartActionByGet(ctx context.Context, in *StartActionByGetRequest, opts ...grpc.CallOption) (*StartActionByGetResponse, error) {
out := new(StartActionByGetResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_StartActionByGet_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) StartActionByGetAndWait(ctx context.Context, in *StartActionByGetAndWaitRequest, opts ...grpc.CallOption) (*StartActionByGetAndWaitResponse, error) {
out := new(StartActionByGetAndWaitResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_StartActionByGetAndWait_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) KillAction(ctx context.Context, in *KillActionRequest, opts ...grpc.CallOption) (*KillActionResponse, error) {
out := new(KillActionResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_KillAction_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) ExecutionStatus(ctx context.Context, in *ExecutionStatusRequest, opts ...grpc.CallOption) (*ExecutionStatusResponse, error) {
out := new(ExecutionStatusResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_ExecutionStatus_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) GetLogs(ctx context.Context, in *GetLogsRequest, opts ...grpc.CallOption) (*GetLogsResponse, error) {
out := new(GetLogsResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_GetLogs_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) ValidateArgumentType(ctx context.Context, in *ValidateArgumentTypeRequest, opts ...grpc.CallOption) (*ValidateArgumentTypeResponse, error) {
out := new(ValidateArgumentTypeResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_ValidateArgumentType_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) WhoAmI(ctx context.Context, in *WhoAmIRequest, opts ...grpc.CallOption) (*WhoAmIResponse, error) {
out := new(WhoAmIResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_WhoAmI_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) SosReport(ctx context.Context, in *SosReportRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) {
out := new(httpbody.HttpBody)
err := c.cc.Invoke(ctx, OliveTinApiService_SosReport_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) DumpVars(ctx context.Context, in *DumpVarsRequest, opts ...grpc.CallOption) (*DumpVarsResponse, error) {
out := new(DumpVarsResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_DumpVars_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) DumpPublicIdActionMap(ctx context.Context, in *DumpPublicIdActionMapRequest, opts ...grpc.CallOption) (*DumpPublicIdActionMapResponse, error) {
out := new(DumpPublicIdActionMapResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_DumpPublicIdActionMap_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) GetReadyz(ctx context.Context, in *GetReadyzRequest, opts ...grpc.CallOption) (*GetReadyzResponse, error) {
out := new(GetReadyzResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_GetReadyz_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) LocalUserLogin(ctx context.Context, in *LocalUserLoginRequest, opts ...grpc.CallOption) (*LocalUserLoginResponse, error) {
out := new(LocalUserLoginResponse)
err := c.cc.Invoke(ctx, OliveTinApiService_LocalUserLogin_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) PasswordHash(ctx context.Context, in *PasswordHashRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) {
out := new(httpbody.HttpBody)
err := c.cc.Invoke(ctx, OliveTinApiService_PasswordHash_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *oliveTinApiServiceClient) Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) {
out := new(httpbody.HttpBody)
err := c.cc.Invoke(ctx, OliveTinApiService_Logout_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// OliveTinApiServiceServer is the server API for OliveTinApiService service.
// All implementations should embed UnimplementedOliveTinApiServiceServer
// for forward compatibility
type OliveTinApiServiceServer interface {
GetDashboardComponents(context.Context, *GetDashboardComponentsRequest) (*GetDashboardComponentsResponse, error)
StartAction(context.Context, *StartActionRequest) (*StartActionResponse, error)
StartActionAndWait(context.Context, *StartActionAndWaitRequest) (*StartActionAndWaitResponse, error)
StartActionByGet(context.Context, *StartActionByGetRequest) (*StartActionByGetResponse, error)
StartActionByGetAndWait(context.Context, *StartActionByGetAndWaitRequest) (*StartActionByGetAndWaitResponse, error)
KillAction(context.Context, *KillActionRequest) (*KillActionResponse, error)
ExecutionStatus(context.Context, *ExecutionStatusRequest) (*ExecutionStatusResponse, error)
GetLogs(context.Context, *GetLogsRequest) (*GetLogsResponse, error)
ValidateArgumentType(context.Context, *ValidateArgumentTypeRequest) (*ValidateArgumentTypeResponse, error)
WhoAmI(context.Context, *WhoAmIRequest) (*WhoAmIResponse, error)
SosReport(context.Context, *SosReportRequest) (*httpbody.HttpBody, error)
DumpVars(context.Context, *DumpVarsRequest) (*DumpVarsResponse, error)
DumpPublicIdActionMap(context.Context, *DumpPublicIdActionMapRequest) (*DumpPublicIdActionMapResponse, error)
GetReadyz(context.Context, *GetReadyzRequest) (*GetReadyzResponse, error)
LocalUserLogin(context.Context, *LocalUserLoginRequest) (*LocalUserLoginResponse, error)
PasswordHash(context.Context, *PasswordHashRequest) (*httpbody.HttpBody, error)
Logout(context.Context, *LogoutRequest) (*httpbody.HttpBody, error)
}
// UnimplementedOliveTinApiServiceServer should be embedded to have forward compatible implementations.
type UnimplementedOliveTinApiServiceServer struct {
}
func (UnimplementedOliveTinApiServiceServer) GetDashboardComponents(context.Context, *GetDashboardComponentsRequest) (*GetDashboardComponentsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetDashboardComponents not implemented")
}
func (UnimplementedOliveTinApiServiceServer) StartAction(context.Context, *StartActionRequest) (*StartActionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method StartAction not implemented")
}
func (UnimplementedOliveTinApiServiceServer) StartActionAndWait(context.Context, *StartActionAndWaitRequest) (*StartActionAndWaitResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method StartActionAndWait not implemented")
}
func (UnimplementedOliveTinApiServiceServer) StartActionByGet(context.Context, *StartActionByGetRequest) (*StartActionByGetResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method StartActionByGet not implemented")
}
func (UnimplementedOliveTinApiServiceServer) StartActionByGetAndWait(context.Context, *StartActionByGetAndWaitRequest) (*StartActionByGetAndWaitResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method StartActionByGetAndWait not implemented")
}
func (UnimplementedOliveTinApiServiceServer) KillAction(context.Context, *KillActionRequest) (*KillActionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method KillAction not implemented")
}
func (UnimplementedOliveTinApiServiceServer) ExecutionStatus(context.Context, *ExecutionStatusRequest) (*ExecutionStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ExecutionStatus not implemented")
}
func (UnimplementedOliveTinApiServiceServer) GetLogs(context.Context, *GetLogsRequest) (*GetLogsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetLogs not implemented")
}
func (UnimplementedOliveTinApiServiceServer) ValidateArgumentType(context.Context, *ValidateArgumentTypeRequest) (*ValidateArgumentTypeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ValidateArgumentType not implemented")
}
func (UnimplementedOliveTinApiServiceServer) WhoAmI(context.Context, *WhoAmIRequest) (*WhoAmIResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WhoAmI not implemented")
}
func (UnimplementedOliveTinApiServiceServer) SosReport(context.Context, *SosReportRequest) (*httpbody.HttpBody, error) {
return nil, status.Errorf(codes.Unimplemented, "method SosReport not implemented")
}
func (UnimplementedOliveTinApiServiceServer) DumpVars(context.Context, *DumpVarsRequest) (*DumpVarsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DumpVars not implemented")
}
func (UnimplementedOliveTinApiServiceServer) DumpPublicIdActionMap(context.Context, *DumpPublicIdActionMapRequest) (*DumpPublicIdActionMapResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DumpPublicIdActionMap not implemented")
}
func (UnimplementedOliveTinApiServiceServer) GetReadyz(context.Context, *GetReadyzRequest) (*GetReadyzResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetReadyz not implemented")
}
func (UnimplementedOliveTinApiServiceServer) LocalUserLogin(context.Context, *LocalUserLoginRequest) (*LocalUserLoginResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method LocalUserLogin not implemented")
}
func (UnimplementedOliveTinApiServiceServer) PasswordHash(context.Context, *PasswordHashRequest) (*httpbody.HttpBody, error) {
return nil, status.Errorf(codes.Unimplemented, "method PasswordHash not implemented")
}
func (UnimplementedOliveTinApiServiceServer) Logout(context.Context, *LogoutRequest) (*httpbody.HttpBody, error) {
return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented")
}
// UnsafeOliveTinApiServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to OliveTinApiServiceServer will
// result in compilation errors.
type UnsafeOliveTinApiServiceServer interface {
mustEmbedUnimplementedOliveTinApiServiceServer()
}
func RegisterOliveTinApiServiceServer(s grpc.ServiceRegistrar, srv OliveTinApiServiceServer) {
s.RegisterService(&OliveTinApiService_ServiceDesc, srv)
}
func _OliveTinApiService_GetDashboardComponents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDashboardComponentsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).GetDashboardComponents(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_GetDashboardComponents_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).GetDashboardComponents(ctx, req.(*GetDashboardComponentsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_StartAction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StartActionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).StartAction(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_StartAction_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).StartAction(ctx, req.(*StartActionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_StartActionAndWait_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StartActionAndWaitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).StartActionAndWait(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_StartActionAndWait_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).StartActionAndWait(ctx, req.(*StartActionAndWaitRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_StartActionByGet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StartActionByGetRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).StartActionByGet(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_StartActionByGet_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).StartActionByGet(ctx, req.(*StartActionByGetRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_StartActionByGetAndWait_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StartActionByGetAndWaitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).StartActionByGetAndWait(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_StartActionByGetAndWait_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).StartActionByGetAndWait(ctx, req.(*StartActionByGetAndWaitRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_KillAction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(KillActionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).KillAction(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_KillAction_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).KillAction(ctx, req.(*KillActionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_ExecutionStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ExecutionStatusRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).ExecutionStatus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_ExecutionStatus_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).ExecutionStatus(ctx, req.(*ExecutionStatusRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_GetLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetLogsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).GetLogs(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_GetLogs_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).GetLogs(ctx, req.(*GetLogsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_ValidateArgumentType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ValidateArgumentTypeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).ValidateArgumentType(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_ValidateArgumentType_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).ValidateArgumentType(ctx, req.(*ValidateArgumentTypeRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_WhoAmI_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(WhoAmIRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).WhoAmI(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_WhoAmI_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).WhoAmI(ctx, req.(*WhoAmIRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_SosReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SosReportRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).SosReport(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_SosReport_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).SosReport(ctx, req.(*SosReportRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_DumpVars_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DumpVarsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).DumpVars(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_DumpVars_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).DumpVars(ctx, req.(*DumpVarsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_DumpPublicIdActionMap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DumpPublicIdActionMapRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).DumpPublicIdActionMap(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_DumpPublicIdActionMap_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).DumpPublicIdActionMap(ctx, req.(*DumpPublicIdActionMapRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_GetReadyz_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetReadyzRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).GetReadyz(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_GetReadyz_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).GetReadyz(ctx, req.(*GetReadyzRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_LocalUserLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LocalUserLoginRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).LocalUserLogin(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_LocalUserLogin_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).LocalUserLogin(ctx, req.(*LocalUserLoginRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_PasswordHash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PasswordHashRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).PasswordHash(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_PasswordHash_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).PasswordHash(ctx, req.(*PasswordHashRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OliveTinApiService_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LogoutRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OliveTinApiServiceServer).Logout(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: OliveTinApiService_Logout_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OliveTinApiServiceServer).Logout(ctx, req.(*LogoutRequest))
}
return interceptor(ctx, in, info, handler)
}
// OliveTinApiService_ServiceDesc is the grpc.ServiceDesc for OliveTinApiService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var OliveTinApiService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "OliveTinApiService",
HandlerType: (*OliveTinApiServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetDashboardComponents",
Handler: _OliveTinApiService_GetDashboardComponents_Handler,
},
{
MethodName: "StartAction",
Handler: _OliveTinApiService_StartAction_Handler,
},
{
MethodName: "StartActionAndWait",
Handler: _OliveTinApiService_StartActionAndWait_Handler,
},
{
MethodName: "StartActionByGet",
Handler: _OliveTinApiService_StartActionByGet_Handler,
},
{
MethodName: "StartActionByGetAndWait",
Handler: _OliveTinApiService_StartActionByGetAndWait_Handler,
},
{
MethodName: "KillAction",
Handler: _OliveTinApiService_KillAction_Handler,
},
{
MethodName: "ExecutionStatus",
Handler: _OliveTinApiService_ExecutionStatus_Handler,
},
{
MethodName: "GetLogs",
Handler: _OliveTinApiService_GetLogs_Handler,
},
{
MethodName: "ValidateArgumentType",
Handler: _OliveTinApiService_ValidateArgumentType_Handler,
},
{
MethodName: "WhoAmI",
Handler: _OliveTinApiService_WhoAmI_Handler,
},
{
MethodName: "SosReport",
Handler: _OliveTinApiService_SosReport_Handler,
},
{
MethodName: "DumpVars",
Handler: _OliveTinApiService_DumpVars_Handler,
},
{
MethodName: "DumpPublicIdActionMap",
Handler: _OliveTinApiService_DumpPublicIdActionMap_Handler,
},
{
MethodName: "GetReadyz",
Handler: _OliveTinApiService_GetReadyz_Handler,
},
{
MethodName: "LocalUserLogin",
Handler: _OliveTinApiService_LocalUserLogin_Handler,
},
{
MethodName: "PasswordHash",
Handler: _OliveTinApiService_PasswordHash_Handler,
},
{
MethodName: "Logout",
Handler: _OliveTinApiService_Logout_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "OliveTin.proto",
}

View File

@ -18,10 +18,13 @@ require (
github.com/gorilla/websocket v1.5.3
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
github.com/jamesread/golure v0.0.0-20250619190948-fa38cbd93cc4
github.com/knadh/koanf/parsers/yaml v1.1.0
github.com/knadh/koanf/providers/env v1.1.0
github.com/knadh/koanf/providers/file v1.2.0
github.com/knadh/koanf/v2 v2.3.0
github.com/prometheus/client_golang v1.22.0
github.com/robfig/cron/v3 v3.0.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.10.0
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
golang.org/x/oauth2 v0.30.0
@ -90,16 +93,20 @@ require (
github.com/jdx/go-netrc v1.0.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/knadh/koanf/maps v0.1.2 // indirect
github.com/knadh/koanf/providers/rawbytes v1.0.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@ -114,16 +121,11 @@ require (
github.com/quic-go/quic-go v0.54.1 // indirect
github.com/rs/cors v1.11.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.9.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/segmentio/encoding v0.5.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.14.0 // indirect
github.com/spf13/cast v1.9.2 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/stoewer/go-strcase v1.3.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/vbatts/tar-split v0.12.1 // indirect
go.lsp.dev/jsonrpc2 v0.10.0 // indirect
@ -138,6 +140,7 @@ require (
go.uber.org/mock v0.5.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v3 v3.0.3 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/exp/typeparams v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/mod v0.25.0 // indirect

View File

@ -88,8 +88,6 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
@ -160,6 +158,18 @@ github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zt
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/yaml v1.1.0 h1:3ltfm9ljprAHt4jxgeYLlFPmUaunuCgu1yILuTXRdM4=
github.com/knadh/koanf/parsers/yaml v1.1.0/go.mod h1:HHmcHXUrp9cOPcuC+2wrr44GTUB0EC+PyfN3HZD9tFg=
github.com/knadh/koanf/providers/env v1.1.0 h1:U2VXPY0f+CsNDkvdsG8GcsnK4ah85WwWyJgef9oQMSc=
github.com/knadh/koanf/providers/env v1.1.0/go.mod h1:QhHHHZ87h9JxJAn2czdEl6pdkNnDh/JS1Vtsyt65hTY=
github.com/knadh/koanf/providers/file v1.2.0 h1:hrUJ6Y9YOA49aNu/RSYzOTFlqzXSCpmYIDXI7OJU6+U=
github.com/knadh/koanf/providers/file v1.2.0/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/providers/rawbytes v1.0.0 h1:MrKDh/HksJlKJmaZjgs4r8aVBb/zsJyc/8qaSnzcdNI=
github.com/knadh/koanf/providers/rawbytes v1.0.0/go.mod h1:KxwYJf1uezTKy6PBtfE+m725NGp4GPVA7XoNTJ/PtLo=
github.com/knadh/koanf/v2 v2.3.0 h1:Qg076dDRFHvqnKG97ZEsi9TAg2/nFTa9hCdcSa1lvlM=
github.com/knadh/koanf/v2 v2.3.0/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -170,8 +180,14 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
@ -188,8 +204,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -224,26 +238,16 @@ github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/segmentio/encoding v0.5.1 h1:LhmgXA5/alniiqfc4cYYrxF6DbUQ3m8MVz4/LQIU1mg=
github.com/segmentio/encoding v0.5.1/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -255,8 +259,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
@ -300,6 +302,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
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=

View File

@ -154,7 +154,7 @@ type Config struct {
BannerMessage string
BannerCSS string
usedConfigDir string
sourceFiles []string
}
type AuthLocalUsersConfig struct {

View File

@ -54,9 +54,9 @@ func (cfg *Config) FindUserByUsername(searchUsername string) *LocalUser {
}
func (cfg *Config) SetDir(dir string) {
cfg.usedConfigDir = dir
cfg.sourceFiles = append(cfg.sourceFiles, dir)
}
func (cfg *Config) GetDir() string {
return cfg.usedConfigDir
return cfg.sourceFiles[len(cfg.sourceFiles)-1]
}

View File

@ -6,10 +6,10 @@ import (
"reflect"
"regexp"
"github.com/knadh/koanf/v2"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
var (
@ -30,16 +30,90 @@ func AddListener(l func()) {
listeners = append(listeners, l)
}
func Reload(cfg *Config) {
if err := viper.UnmarshalExact(&cfg, viper.DecodeHook(envDecodeHookFunc)); err != nil {
log.Errorf("Config unmarshal error %+v", err)
os.Exit(1)
func AppendSource(cfg *Config, k *koanf.Koanf, configPath string) {
log.Infof("Appending cfg source: %s", configPath)
// Try default unmarshaling first
err := k.Unmarshal(".", cfg)
if err != nil {
log.Errorf("Error unmarshalling config: %v", err)
return
}
// If actions are not loaded by default unmarshaling, try manual unmarshaling
// This is a workaround for a koanf issue where []*Action fields are not unmarshaled correctly
if len(cfg.Actions) == 0 && k.Exists("actions") {
var actions []*Action
err := k.Unmarshal("actions", &actions)
if err != nil {
log.Errorf("Error manually unmarshaling actions: %v", err)
} else {
cfg.Actions = actions
}
}
// If dashboards are not loaded by default unmarshaling, try manual unmarshaling
// This is a workaround for a koanf issue where []*DashboardComponent fields are not unmarshaled correctly
if len(cfg.Dashboards) == 0 && k.Exists("dashboards") {
var dashboards []*DashboardComponent
err := k.Unmarshal("dashboards", &dashboards)
if err != nil {
log.Errorf("Error manually unmarshaling dashboards: %v", err)
} else {
cfg.Dashboards = dashboards
}
}
// If entities are not loaded by default unmarshaling, try manual unmarshaling
// This is a workaround for a koanf issue where []*EntityFile fields are not unmarshaled correctly
if len(cfg.Entities) == 0 && k.Exists("entities") {
var entities []*EntityFile
err := k.Unmarshal("entities", &entities)
if err != nil {
log.Errorf("Error manually unmarshaling entities: %v", err)
} else {
cfg.Entities = entities
}
}
// Manual field assignment for other config fields that might not be unmarshaled correctly
if k.Exists("showFooter") {
cfg.ShowFooter = k.Bool("showFooter")
}
if k.Exists("showNavigation") {
cfg.ShowNavigation = k.Bool("showNavigation")
}
if k.Exists("checkForUpdates") {
cfg.CheckForUpdates = k.Bool("checkForUpdates")
}
if k.Exists("pageTitle") {
cfg.PageTitle = k.String("pageTitle")
}
// Handle defaultPolicy nested struct
if k.Exists("defaultPolicy") {
if k.Exists("defaultPolicy.showDiagnostics") {
cfg.DefaultPolicy.ShowDiagnostics = k.Bool("defaultPolicy.showDiagnostics")
}
if k.Exists("defaultPolicy.showLogList") {
cfg.DefaultPolicy.ShowLogList = k.Bool("defaultPolicy.showLogList")
}
}
// Handle prometheus nested struct
if k.Exists("prometheus") {
if k.Exists("prometheus.enabled") {
cfg.Prometheus.Enabled = k.Bool("prometheus.enabled")
}
if k.Exists("prometheus.defaultGoMetrics") {
cfg.Prometheus.DefaultGoMetrics = k.Bool("prometheus.defaultGoMetrics")
}
}
metricConfigReloadedCount.Inc()
metricConfigActionCount.Set(float64(len(cfg.Actions)))
cfg.SetDir(filepath.Dir(viper.ConfigFileUsed()))
cfg.SetDir(filepath.Dir(configPath))
cfg.Sanitize()
for _, l := range listeners {
@ -49,19 +123,23 @@ func Reload(cfg *Config) {
var envRegex = regexp.MustCompile(`\${{ *?(\S+) *?}}`)
func envDecodeHookFunc(from reflect.Value, to reflect.Value) (any, error) {
func envDecodeHookFunc(from reflect.Type, to reflect.Type, data any) (any, error) {
log.Debugf("envDecodeHookFunc called: from=%v, to=%v, data=%v", from, to, data)
if from.Kind() != reflect.String {
return from.Interface(), nil
return data, nil
}
input := from.Interface().(string)
input := data.(string)
log.Debugf("Processing string input: %q", input)
output := envRegex.ReplaceAllStringFunc(input, func(match string) string {
submatches := envRegex.FindStringSubmatch(match)
key := submatches[1]
val, set := os.LookupEnv(key)
log.Debugf("Environment variable %q: set=%v, value=%q", key, set, val)
if !set {
log.Warnf("Config file references unset environment variable: \"%s\"", key)
}
return val
})
log.Debugf("Environment variable interpolation result: %q -> %q", input, output)
return output, nil
}

View File

@ -2,27 +2,28 @@ package config
import (
"os"
"strings"
"testing"
"github.com/spf13/viper"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/rawbytes"
"github.com/knadh/koanf/v2"
"github.com/stretchr/testify/assert"
)
var stringEnvConfigYaml = `
pageTitle: ${{ INPUT }}
PageTitle: ${{ INPUT }}
`
var stringEnvInterpolationConfigYaml = `
pageTitle: Olivetin - ${{ INPUT }}
PageTitle: Olivetin - ${{ INPUT }}
`
var boolEnvConfigYaml = `
checkForUpdates: ${{ INPUT }}
CheckForUpdates: ${{ INPUT }}
`
var numericEnvConfigYaml = `
logHistoryPageSize: ${{ INPUT }}
LogHistoryPageSize: ${{ INPUT }}
`
var argsSyntaxConfigYaml = `
@ -80,22 +81,61 @@ var envConfigTests = []struct {
// Test that unset variables turn into zero numbers.
{numericEnvConfigYaml, "", int64(0), logHistoryPageSizeSelector},
// Test that it doesn't interfere with similar arguments
{argsSyntaxConfigYaml, "5", "ping {{ host }} -c 5", func(cfg *Config) any { return cfg.Actions[0].Shell }},
{argsSyntaxConfigYaml, "5", "ping {{ host }} -c 5", func(cfg *Config) any {
if len(cfg.Actions) > 0 {
return cfg.Actions[0].Shell
}
return ""
}},
}
func TestEnvInConfig(t *testing.T) {
viper.SetConfigType("yaml")
for _, tt := range envConfigTests {
err := viper.ReadConfig(strings.NewReader(tt.yaml))
assert.Nil(t, err, "Viper read config file with environment variable syntax")
cfg := DefaultConfig()
if tt.input != "" {
os.Setenv("INPUT", tt.input)
}
cfg := DefaultConfig()
Reload(cfg)
// Process the YAML content to replace environment variables
processedYaml := envRegex.ReplaceAllStringFunc(tt.yaml, func(match string) string {
submatches := envRegex.FindStringSubmatch(match)
key := submatches[1]
val, _ := os.LookupEnv(key)
return val
})
k := koanf.New(".")
err := k.Load(rawbytes.Provider([]byte(processedYaml)), yaml.Parser())
if err != nil {
t.Errorf("Error loading YAML: %v", err)
continue
}
// Try default unmarshaling
err = k.Unmarshal(".", cfg)
if err != nil {
t.Errorf("Error unmarshalling config: %v", err)
continue
}
// Manual field assignment for testing (since default unmarshaling has issues with field mapping)
if k.Exists("PageTitle") {
cfg.PageTitle = k.String("PageTitle")
}
if k.Exists("CheckForUpdates") {
cfg.CheckForUpdates = k.Bool("CheckForUpdates")
}
if k.Exists("LogHistoryPageSize") {
cfg.LogHistoryPageSize = k.Int64("LogHistoryPageSize")
}
if k.Exists("actions") {
var actions []*Action
if err := k.Unmarshal("actions", &actions); err == nil {
cfg.Actions = actions
}
}
field := tt.selector(cfg)
assert.Equal(t, tt.output, field, "Unmarshaled config field doesn't match expected value: env=\"%s\"", tt.input)

View File

@ -32,10 +32,14 @@ func AddListener(l func()) {
func SetupEntityFileWatchers(cfg *config.Config) {
configDir := cfg.GetDir()
configDirVar := filepath.Join(configDir, "var") // for development purposes
// Only use var directory if not in integration test mode
absConfigDir, _ := filepath.Abs(configDir)
if !strings.Contains(absConfigDir, "integration-tests") {
configDirVar := filepath.Join(configDir, "var") // for development purposes
if _, err := os.Stat(configDirVar); err == nil {
configDir = configDirVar
if _, err := os.Stat(configDirVar); err == nil {
configDir = configDirVar
}
}
for entityIndex := range cfg.Entities { // #337 - iterate by key, not by value
@ -112,20 +116,19 @@ func loadEntityFileYaml(filename string, entityname string) {
return
}
data := make([]map[string]any, 1)
var data []map[string]any
err = yaml.Unmarshal(yfile, &data)
if err != nil {
log.Errorf("Unmarshal: %v", err)
return
}
updateSvFromFile(entityname, data)
}
func updateSvFromFile(entityname string, data []map[string]any) {
log.Debugf("updateSvFromFile: %+v", data)
ClearEntities(entityname)
for i, mapp := range data {

View File

@ -2,6 +2,8 @@ package main
import (
"flag"
"path/filepath"
"strings"
log "github.com/sirupsen/logrus"
@ -21,8 +23,11 @@ import (
"strconv"
config "github.com/OliveTin/OliveTin/internal/config"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/env"
"github.com/knadh/koanf/providers/file"
"github.com/knadh/koanf/v2"
)
var (
@ -35,7 +40,7 @@ var (
func init() {
initLog()
initViperConfig(initCliFlags())
initConfig(initCliFlags())
initCheckEnvironment()
@ -104,29 +109,63 @@ func getBasePort() int {
return basePort
}
func initViperConfig(configDir string) {
viper.AutomaticEnv()
viper.SetConfigName("config.yaml")
viper.SetConfigType("yaml")
viper.AddConfigPath(configDir)
viper.AddConfigPath(servicehost.GetConfigFilePath())
viper.AddConfigPath("/config") // For containers.
viper.AddConfigPath("/etc/OliveTin/")
func initConfig(configDir string) {
k := koanf.New(".")
k.Load(env.Provider(".", ".", nil), nil)
if err := viper.ReadInConfig(); err != nil {
log.Errorf("Config file error at startup. %s", err)
os.Exit(1)
directories := []string{
configDir,
}
// Only load additional configs if not in integration test mode
absConfigDir, _ := filepath.Abs(configDir)
if !strings.Contains(absConfigDir, "integration-tests") {
directories = append(directories,
servicehost.GetConfigFilePath(),
"/config", // For containers.
"/etc/OliveTin/",
)
}
var firstConfigPath string
for _, directory := range directories {
configPath := filepath.Join(directory, "config.yaml")
log.Debugf("Checking config path: %s", configPath)
if _, err := os.Stat(configPath); err != nil {
log.Debugf("Config file not found at %s: %v", configPath, err)
continue
}
if firstConfigPath == "" {
firstConfigPath = configPath
}
log.Infof("Loading config from %s", configPath)
f := file.Provider(configPath)
if err := k.Load(f, yaml.Parser()); err != nil {
log.Fatalf("error loading config from %s: %v", configPath, err)
os.Exit(1)
}
f.Watch(func(evt interface{}, err error) {
log.Infof("config file changed: %v", evt)
k.Load(f, yaml.Parser())
config.AppendSource(cfg, k, configPath)
})
}
cfg = config.DefaultConfigWithBasePort(getBasePort())
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
log.Infof("Config file changed: %s", viper.ConfigFileUsed())
config.Reload(cfg)
})
if firstConfigPath != "" {
config.AppendSource(cfg, k, firstConfigPath)
} else {
config.AppendSource(cfg, k, "base")
}
config.Reload(cfg)
}
func initInstallationInfo() {