refactor: Moved proto files into own folder (#537)

This commit is contained in:
James Read 2025-03-21 02:41:41 +00:00 committed by GitHub
parent 486253b253
commit 270f20ec75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 929 additions and 503 deletions

32
.github/workflows/build-buf.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Buf CI
on:
push:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
delete:
permissions:
contents: read
pull-requests: write
jobs:
buf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: true
- name: grpc
run: make -w grpc
- uses: bufbuild/buf-action@v1
with:
token: ${{ secrets.BUF_TOKEN }}
# Change setup_only to true if you only want to set up the Action and not execute other commands.
# Otherwise, you can delete this line--the default is false.
setup_only: false
# Optional GitHub token for API requests. Ensures requests aren't rate limited.
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -71,6 +71,7 @@ jobs:
- name: Archive integration tests - name: Archive integration tests
uses: actions/upload-artifact@v4.3.1 uses: actions/upload-artifact@v4.3.1
if: always()
with: with:
name: "OliveTin-integration-tests-${{ env.DATE }}-${{ github.sha }}" name: "OliveTin-integration-tests-${{ env.DATE }}-${{ github.sha }}"
path: | path: |

View File

@ -50,7 +50,7 @@ go-tools:
go install "google.golang.org/protobuf/cmd/protoc-gen-go" go install "google.golang.org/protobuf/cmd/protoc-gen-go"
grpc: go-tools grpc: go-tools
buf generate $(MAKE) -wC proto
dist: protoc dist: protoc

View File

@ -1,7 +0,0 @@
# Generated by buf. DO NOT EDIT.
version: v1
deps:
- remote: buf.build
owner: googleapis
repository: googleapis
commit: e9fcfb66f77242e5b8fd4564d7a01033

View File

@ -19,6 +19,10 @@ export function takeScreenshotOnFailure (test, webdriver) {
export function takeScreenshot (webdriver, title) { export function takeScreenshot (webdriver, title) {
return webdriver.takeScreenshot().then((img) => { return webdriver.takeScreenshot().then((img) => {
fs.mkdirSync('screenshots', { recursive: true }); fs.mkdirSync('screenshots', { recursive: true });
title = title.replaceAll(/[\(\)\|\*\<\>\:]/g, "_")
title = 'failed-test.' + title
fs.writeFileSync('screenshots/' + title + '.png', img, 'base64') fs.writeFileSync('screenshots/' + title + '.png', img, 'base64')
}) })
} }

File diff suppressed because it is too large Load Diff

View File

@ -11,12 +11,12 @@
"author": "", "author": "",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"devDependencies": { "devDependencies": {
"chai": "^5.1.0", "chai": "^5.2.0",
"eslint": "^8.51.0", "eslint": "^9.22.0",
"mocha": "^10.8.2", "mocha": "^11.1.0",
"selenium-webdriver": "^4.19.0" "selenium-webdriver": "^4.29.0"
}, },
"dependencies": { "dependencies": {
"wait-on": "^7.2.0" "wait-on": "^8.0.3"
} }
} }

View File

@ -2,8 +2,8 @@ import { describe, it, before, after } from 'mocha'
import { expect } from 'chai' import { expect } from 'chai'
import { By, until, Condition } from 'selenium-webdriver' import { By, until, Condition } from 'selenium-webdriver'
//import * as waitOn from 'wait-on' //import * as waitOn from 'wait-on'
import { import {
getRootAndWait, getRootAndWait,
getActionButtons, getActionButtons,
takeScreenshotOnFailure, takeScreenshotOnFailure,
} from '../lib/elements.js' } from '../lib/elements.js'
@ -96,6 +96,7 @@ describe('config: general', function () {
expect(await title.getAttribute('innerText')).to.be.equal('?') expect(await title.getAttribute('innerText')).to.be.equal('?')
const dialogErr = await webdriver.findElement(By.id('big-error')) const dialogErr = await webdriver.findElement(By.id('big-error'))
console.log("big error is: " + dialogErr.innerHTML)
expect(dialogErr).to.not.be.null expect(dialogErr).to.not.be.null
expect(await dialogErr.isDisplayed()).to.be.false expect(await dialogErr.isDisplayed()).to.be.false
}) })

View File

@ -3,7 +3,7 @@ package grpcapi
import ( import (
ctx "context" ctx "context"
pb "github.com/OliveTin/OliveTin/gen/grpc" apiv1 "github.com/OliveTin/OliveTin/gen/grpc/olivetin/api/v1"
"github.com/google/uuid" "github.com/google/uuid"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"google.golang.org/genproto/googleapis/api/httpbody" "google.golang.org/genproto/googleapis/api/httpbody"
@ -28,13 +28,13 @@ var (
type oliveTinAPI struct { type oliveTinAPI struct {
// Uncomment this if you want to allow undefined methods during dev. // Uncomment this if you want to allow undefined methods during dev.
// pb.UnimplementedOliveTinApiServiceServer // apiv1.UnimplementedOliveTinApiServiceServer
executor *executor.Executor executor *executor.Executor
} }
func (api *oliveTinAPI) KillAction(ctx ctx.Context, req *pb.KillActionRequest) (*pb.KillActionResponse, error) { func (api *oliveTinAPI) KillAction(ctx ctx.Context, req *apiv1.KillActionRequest) (*apiv1.KillActionResponse, error) {
ret := &pb.KillActionResponse{ ret := &apiv1.KillActionResponse{
ExecutionTrackingId: req.ExecutionTrackingId, ExecutionTrackingId: req.ExecutionTrackingId,
} }
@ -61,7 +61,7 @@ func (api *oliveTinAPI) KillAction(ctx ctx.Context, req *pb.KillActionRequest) (
return ret, nil return ret, nil
} }
func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest) (*pb.StartActionResponse, error) { func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *apiv1.StartActionRequest) (*apiv1.StartActionResponse, error) {
args := make(map[string]string) args := make(map[string]string)
for _, arg := range req.Arguments { for _, arg := range req.Arguments {
@ -89,12 +89,12 @@ func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest)
api.executor.ExecRequest(&execReq) api.executor.ExecRequest(&execReq)
return &pb.StartActionResponse{ return &apiv1.StartActionResponse{
ExecutionTrackingId: execReq.TrackingID, ExecutionTrackingId: execReq.TrackingID,
}, nil }, nil
} }
func (api *oliveTinAPI) PasswordHash(ctx ctx.Context, req *pb.PasswordHashRequest) (*httpbody.HttpBody, error) { func (api *oliveTinAPI) PasswordHash(ctx ctx.Context, req *apiv1.PasswordHashRequest) (*httpbody.HttpBody, error) {
hash, err := createHash(req.Password) hash, err := createHash(req.Password)
if err != nil { if err != nil {
@ -109,7 +109,7 @@ func (api *oliveTinAPI) PasswordHash(ctx ctx.Context, req *pb.PasswordHashReques
return ret, nil return ret, nil
} }
func (api *oliveTinAPI) LocalUserLogin(ctx ctx.Context, req *pb.LocalUserLoginRequest) (*pb.LocalUserLoginResponse, error) { func (api *oliveTinAPI) LocalUserLogin(ctx ctx.Context, req *apiv1.LocalUserLoginRequest) (*apiv1.LocalUserLoginResponse, error) {
match := checkUserPassword(cfg, req.Username, req.Password) match := checkUserPassword(cfg, req.Username, req.Password)
if match { if match {
@ -124,12 +124,12 @@ func (api *oliveTinAPI) LocalUserLogin(ctx ctx.Context, req *pb.LocalUserLoginRe
}).Warn("LocalUserLogin: User login failed.") }).Warn("LocalUserLogin: User login failed.")
} }
return &pb.LocalUserLoginResponse{ return &apiv1.LocalUserLoginResponse{
Success: match, Success: match,
}, nil }, nil
} }
func (api *oliveTinAPI) StartActionAndWait(ctx ctx.Context, req *pb.StartActionAndWaitRequest) (*pb.StartActionAndWaitResponse, error) { func (api *oliveTinAPI) StartActionAndWait(ctx ctx.Context, req *apiv1.StartActionAndWaitRequest) (*apiv1.StartActionAndWaitResponse, error) {
args := make(map[string]string) args := make(map[string]string)
for _, arg := range req.Arguments { for _, arg := range req.Arguments {
@ -150,7 +150,7 @@ func (api *oliveTinAPI) StartActionAndWait(ctx ctx.Context, req *pb.StartActionA
internalLogEntry, ok := api.executor.GetLog(execReq.TrackingID) internalLogEntry, ok := api.executor.GetLog(execReq.TrackingID)
if ok { if ok {
return &pb.StartActionAndWaitResponse{ return &apiv1.StartActionAndWaitResponse{
LogEntry: internalLogEntryToPb(internalLogEntry), LogEntry: internalLogEntryToPb(internalLogEntry),
}, nil }, nil
} else { } else {
@ -158,7 +158,7 @@ func (api *oliveTinAPI) StartActionAndWait(ctx ctx.Context, req *pb.StartActionA
} }
} }
func (api *oliveTinAPI) StartActionByGet(ctx ctx.Context, req *pb.StartActionByGetRequest) (*pb.StartActionByGetResponse, error) { func (api *oliveTinAPI) StartActionByGet(ctx ctx.Context, req *apiv1.StartActionByGetRequest) (*apiv1.StartActionByGetResponse, error) {
args := make(map[string]string) args := make(map[string]string)
execReq := executor.ExecutionRequest{ execReq := executor.ExecutionRequest{
@ -171,12 +171,12 @@ func (api *oliveTinAPI) StartActionByGet(ctx ctx.Context, req *pb.StartActionByG
_, uniqueTrackingId := api.executor.ExecRequest(&execReq) _, uniqueTrackingId := api.executor.ExecRequest(&execReq)
return &pb.StartActionByGetResponse{ return &apiv1.StartActionByGetResponse{
ExecutionTrackingId: uniqueTrackingId, ExecutionTrackingId: uniqueTrackingId,
}, nil }, nil
} }
func (api *oliveTinAPI) StartActionByGetAndWait(ctx ctx.Context, req *pb.StartActionByGetAndWaitRequest) (*pb.StartActionByGetAndWaitResponse, error) { func (api *oliveTinAPI) StartActionByGetAndWait(ctx ctx.Context, req *apiv1.StartActionByGetAndWaitRequest) (*apiv1.StartActionByGetAndWaitResponse, error) {
args := make(map[string]string) args := make(map[string]string)
execReq := executor.ExecutionRequest{ execReq := executor.ExecutionRequest{
@ -193,7 +193,7 @@ func (api *oliveTinAPI) StartActionByGetAndWait(ctx ctx.Context, req *pb.StartAc
internalLogEntry, ok := api.executor.GetLog(execReq.TrackingID) internalLogEntry, ok := api.executor.GetLog(execReq.TrackingID)
if ok { if ok {
return &pb.StartActionByGetAndWaitResponse{ return &apiv1.StartActionByGetAndWaitResponse{
LogEntry: internalLogEntryToPb(internalLogEntry), LogEntry: internalLogEntryToPb(internalLogEntry),
}, nil }, nil
} else { } else {
@ -201,8 +201,8 @@ func (api *oliveTinAPI) StartActionByGetAndWait(ctx ctx.Context, req *pb.StartAc
} }
} }
func internalLogEntryToPb(logEntry *executor.InternalLogEntry) *pb.LogEntry { func internalLogEntryToPb(logEntry *executor.InternalLogEntry) *apiv1.LogEntry {
return &pb.LogEntry{ return &apiv1.LogEntry{
ActionTitle: logEntry.ActionTitle, ActionTitle: logEntry.ActionTitle,
ActionIcon: logEntry.ActionIcon, ActionIcon: logEntry.ActionIcon,
ActionId: logEntry.ActionId, ActionId: logEntry.ActionId,
@ -246,8 +246,8 @@ func getMostRecentExecutionStatusById(api *oliveTinAPI, actionId string) *execut
return ile return ile
} }
func (api *oliveTinAPI) ExecutionStatus(ctx ctx.Context, req *pb.ExecutionStatusRequest) (*pb.ExecutionStatusResponse, error) { func (api *oliveTinAPI) ExecutionStatus(ctx ctx.Context, req *apiv1.ExecutionStatusRequest) (*apiv1.ExecutionStatusResponse, error) {
res := &pb.ExecutionStatusResponse{} res := &apiv1.ExecutionStatusResponse{}
var ile *executor.InternalLogEntry var ile *executor.InternalLogEntry
@ -268,7 +268,7 @@ func (api *oliveTinAPI) ExecutionStatus(ctx ctx.Context, req *pb.ExecutionStatus
} }
/** /**
func (api *oliveTinAPI) WatchExecution(req *pb.WatchExecutionRequest, srv pb.OliveTinApi_WatchExecutionServer) error { func (api *oliveTinAPI) WatchExecution(req *apiv1.WatchExecutionRequest, srv apiv1.OliveTinApi_WatchExecutionServer) error {
log.Infof("Watch") log.Infof("Watch")
if logEntry, ok := api.executor.Logs[req.ExecutionUuid]; !ok { if logEntry, ok := api.executor.Logs[req.ExecutionUuid]; !ok {
@ -284,7 +284,7 @@ func (api *oliveTinAPI) WatchExecution(req *pb.WatchExecutionRequest, srv pb.Oli
log.Infof("%v %v", red, err) log.Infof("%v %v", red, err)
srv.Send(&pb.WatchExecutionUpdate{ srv.Send(&apiv1.WatchExecutionUpdate{
Update: string(tmp), Update: string(tmp),
}) })
} }
@ -295,7 +295,7 @@ func (api *oliveTinAPI) WatchExecution(req *pb.WatchExecutionRequest, srv pb.Oli
} }
*/ */
func (api *oliveTinAPI) Logout(ctx ctx.Context, req *pb.LogoutRequest) (*httpbody.HttpBody, error) { func (api *oliveTinAPI) Logout(ctx ctx.Context, req *apiv1.LogoutRequest) (*httpbody.HttpBody, error) {
user := acl.UserFromContext(ctx, cfg) user := acl.UserFromContext(ctx, cfg)
grpc.SendHeader(ctx, metadata.Pairs("logout-provider", user.Provider)) grpc.SendHeader(ctx, metadata.Pairs("logout-provider", user.Provider))
@ -304,7 +304,7 @@ func (api *oliveTinAPI) Logout(ctx ctx.Context, req *pb.LogoutRequest) (*httpbod
return nil, nil return nil, nil
} }
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) { func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *apiv1.GetDashboardComponentsRequest) (*apiv1.GetDashboardComponentsResponse, error) {
user := acl.UserFromContext(ctx, cfg) user := acl.UserFromContext(ctx, cfg)
if user.IsGuest() && cfg.AuthRequireGuestsToLogin { if user.IsGuest() && cfg.AuthRequireGuestsToLogin {
@ -330,10 +330,10 @@ func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashb
return res, nil return res, nil
} }
func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *pb.GetLogsRequest) (*pb.GetLogsResponse, error) { func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *apiv1.GetLogsRequest) (*apiv1.GetLogsResponse, error) {
user := acl.UserFromContext(ctx, cfg) user := acl.UserFromContext(ctx, cfg)
ret := &pb.GetLogsResponse{} ret := &apiv1.GetLogsResponse{}
logEntries, countRemaining := api.executor.GetLogTrackingIds(req.StartOffset, cfg.LogHistoryPageSize) logEntries, countRemaining := api.executor.GetLogTrackingIds(req.StartOffset, cfg.LogHistoryPageSize)
@ -358,7 +358,7 @@ This function is ONLY a helper for the UI - the arguments are validated properly
on the StartAction -> Executor chain. This is here basically to provide helpful on the StartAction -> Executor chain. This is here basically to provide helpful
error messages more quickly before starting the action. error messages more quickly before starting the action.
*/ */
func (api *oliveTinAPI) ValidateArgumentType(ctx ctx.Context, req *pb.ValidateArgumentTypeRequest) (*pb.ValidateArgumentTypeResponse, error) { func (api *oliveTinAPI) ValidateArgumentType(ctx ctx.Context, req *apiv1.ValidateArgumentTypeRequest) (*apiv1.ValidateArgumentTypeResponse, error) {
err := executor.TypeSafetyCheck("", req.Value, req.Type) err := executor.TypeSafetyCheck("", req.Value, req.Type)
desc := "" desc := ""
@ -366,16 +366,16 @@ func (api *oliveTinAPI) ValidateArgumentType(ctx ctx.Context, req *pb.ValidateAr
desc = err.Error() desc = err.Error()
} }
return &pb.ValidateArgumentTypeResponse{ return &apiv1.ValidateArgumentTypeResponse{
Valid: err == nil, Valid: err == nil,
Description: desc, Description: desc,
}, nil }, nil
} }
func (api *oliveTinAPI) WhoAmI(ctx ctx.Context, req *pb.WhoAmIRequest) (*pb.WhoAmIResponse, error) { func (api *oliveTinAPI) WhoAmI(ctx ctx.Context, req *apiv1.WhoAmIRequest) (*apiv1.WhoAmIResponse, error) {
user := acl.UserFromContext(ctx, cfg) user := acl.UserFromContext(ctx, cfg)
res := &pb.WhoAmIResponse{ res := &apiv1.WhoAmIResponse{
AuthenticatedUser: user.Username, AuthenticatedUser: user.Username,
Usergroup: user.Usergroup, Usergroup: user.Usergroup,
Provider: user.Provider, Provider: user.Provider,
@ -388,7 +388,7 @@ func (api *oliveTinAPI) WhoAmI(ctx ctx.Context, req *pb.WhoAmIRequest) (*pb.WhoA
return res, nil return res, nil
} }
func (api *oliveTinAPI) SosReport(ctx ctx.Context, req *pb.SosReportRequest) (*httpbody.HttpBody, error) { func (api *oliveTinAPI) SosReport(ctx ctx.Context, req *apiv1.SosReportRequest) (*httpbody.HttpBody, error) {
sos := installationinfo.GetSosReport() sos := installationinfo.GetSosReport()
if !cfg.InsecureAllowDumpSos { if !cfg.InsecureAllowDumpSos {
@ -404,8 +404,8 @@ func (api *oliveTinAPI) SosReport(ctx ctx.Context, req *pb.SosReportRequest) (*h
return ret, nil return ret, nil
} }
func (api *oliveTinAPI) DumpVars(ctx ctx.Context, req *pb.DumpVarsRequest) (*pb.DumpVarsResponse, error) { func (api *oliveTinAPI) DumpVars(ctx ctx.Context, req *apiv1.DumpVarsRequest) (*apiv1.DumpVarsResponse, error) {
res := &pb.DumpVarsResponse{} res := &apiv1.DumpVarsResponse{}
if !cfg.InsecureAllowDumpVars { if !cfg.InsecureAllowDumpVars {
res.Alert = "Dumping variables is not allowed by default because it is insecure." res.Alert = "Dumping variables is not allowed by default because it is insecure."
@ -419,9 +419,9 @@ func (api *oliveTinAPI) DumpVars(ctx ctx.Context, req *pb.DumpVarsRequest) (*pb.
return res, nil return res, nil
} }
func (api *oliveTinAPI) DumpPublicIdActionMap(ctx ctx.Context, req *pb.DumpPublicIdActionMapRequest) (*pb.DumpPublicIdActionMapResponse, error) { func (api *oliveTinAPI) DumpPublicIdActionMap(ctx ctx.Context, req *apiv1.DumpPublicIdActionMapRequest) (*apiv1.DumpPublicIdActionMapResponse, error) {
res := &pb.DumpPublicIdActionMapResponse{} res := &apiv1.DumpPublicIdActionMapResponse{}
res.Contents = make(map[string]*pb.ActionEntityPair) res.Contents = make(map[string]*apiv1.ActionEntityPair)
if !cfg.InsecureAllowDumpActionMap { if !cfg.InsecureAllowDumpActionMap {
res.Alert = "Dumping Public IDs is disallowed." res.Alert = "Dumping Public IDs is disallowed."
@ -432,7 +432,7 @@ func (api *oliveTinAPI) DumpPublicIdActionMap(ctx ctx.Context, req *pb.DumpPubli
api.executor.MapActionIdToBindingLock.RLock() api.executor.MapActionIdToBindingLock.RLock()
for k, v := range api.executor.MapActionIdToBinding { for k, v := range api.executor.MapActionIdToBinding {
res.Contents[k] = &pb.ActionEntityPair{ res.Contents[k] = &apiv1.ActionEntityPair{
ActionTitle: v.Action.Title, ActionTitle: v.Action.Title,
EntityPrefix: v.EntityPrefix, EntityPrefix: v.EntityPrefix,
} }
@ -445,8 +445,8 @@ func (api *oliveTinAPI) DumpPublicIdActionMap(ctx ctx.Context, req *pb.DumpPubli
return res, nil return res, nil
} }
func (api *oliveTinAPI) GetReadyz(ctx ctx.Context, req *pb.GetReadyzRequest) (*pb.GetReadyzResponse, error) { func (api *oliveTinAPI) GetReadyz(ctx ctx.Context, req *apiv1.GetReadyzRequest) (*apiv1.GetReadyzResponse, error) {
res := &pb.GetReadyzResponse{ res := &apiv1.GetReadyzResponse{
Status: "OK", Status: "OK",
} }
@ -468,7 +468,7 @@ func Start(globalConfig *config.Config, ex *executor.Executor) {
} }
grpcServer := grpc.NewServer() grpcServer := grpc.NewServer()
pb.RegisterOliveTinApiServiceServer(grpcServer, newServer(ex)) apiv1.RegisterOliveTinApiServiceServer(grpcServer, newServer(ex))
err = grpcServer.Serve(lis) err = grpcServer.Serve(lis)

View File

@ -1,7 +1,7 @@
package grpcapi package grpcapi
import ( import (
pb "github.com/OliveTin/OliveTin/gen/grpc" apiv1 "github.com/OliveTin/OliveTin/gen/grpc/olivetin/api/v1"
acl "github.com/OliveTin/OliveTin/internal/acl" acl "github.com/OliveTin/OliveTin/internal/acl"
config "github.com/OliveTin/OliveTin/internal/config" config "github.com/OliveTin/OliveTin/internal/config"
executor "github.com/OliveTin/OliveTin/internal/executor" executor "github.com/OliveTin/OliveTin/internal/executor"
@ -9,8 +9,8 @@ import (
"sort" "sort"
) )
func buildDashboardResponse(ex *executor.Executor, cfg *config.Config, user *acl.AuthenticatedUser) *pb.GetDashboardComponentsResponse { func buildDashboardResponse(ex *executor.Executor, cfg *config.Config, user *acl.AuthenticatedUser) *apiv1.GetDashboardComponentsResponse {
res := &pb.GetDashboardComponentsResponse{ res := &apiv1.GetDashboardComponentsResponse{
AuthenticatedUser: user.Username, AuthenticatedUser: user.Username,
AuthenticatedUserProvider: user.Provider, AuthenticatedUserProvider: user.Provider,
} }
@ -38,10 +38,10 @@ func buildDashboardResponse(ex *executor.Executor, cfg *config.Config, user *acl
return res return res
} }
func buildAction(actionId string, actionBinding *executor.ActionBinding, user *acl.AuthenticatedUser) *pb.Action { func buildAction(actionId string, actionBinding *executor.ActionBinding, user *acl.AuthenticatedUser) *apiv1.Action {
action := actionBinding.Action action := actionBinding.Action
btn := pb.Action{ btn := apiv1.Action{
Id: actionId, Id: actionId,
Title: sv.ReplaceEntityVars(actionBinding.EntityPrefix, action.Title), Title: sv.ReplaceEntityVars(actionBinding.EntityPrefix, action.Title),
Icon: action.Icon, Icon: action.Icon,
@ -51,7 +51,7 @@ func buildAction(actionId string, actionBinding *executor.ActionBinding, user *a
} }
for _, cfgArg := range action.Arguments { for _, cfgArg := range action.Arguments {
pbArg := pb.ActionArgument{ pbArg := apiv1.ActionArgument{
Name: cfgArg.Name, Name: cfgArg.Name,
Title: cfgArg.Title, Title: cfgArg.Title,
Type: cfgArg.Type, Type: cfgArg.Type,
@ -67,7 +67,7 @@ func buildAction(actionId string, actionBinding *executor.ActionBinding, user *a
return &btn return &btn
} }
func buildChoices(arg config.ActionArgument) []*pb.ActionArgumentChoice { func buildChoices(arg config.ActionArgument) []*apiv1.ActionArgumentChoice {
if arg.Entity != "" && len(arg.Choices) == 1 { if arg.Entity != "" && len(arg.Choices) == 1 {
return buildChoicesEntity(arg.Choices[0], arg.Entity) return buildChoicesEntity(arg.Choices[0], arg.Entity)
} else { } else {
@ -75,15 +75,15 @@ func buildChoices(arg config.ActionArgument) []*pb.ActionArgumentChoice {
} }
} }
func buildChoicesEntity(firstChoice config.ActionArgumentChoice, entityTitle string) []*pb.ActionArgumentChoice { func buildChoicesEntity(firstChoice config.ActionArgumentChoice, entityTitle string) []*apiv1.ActionArgumentChoice {
ret := []*pb.ActionArgumentChoice{} ret := []*apiv1.ActionArgumentChoice{}
entityCount := sv.GetEntityCount(entityTitle) entityCount := sv.GetEntityCount(entityTitle)
for i := 0; i < entityCount; i++ { for i := 0; i < entityCount; i++ {
prefix := sv.GetEntityPrefix(entityTitle, i) prefix := sv.GetEntityPrefix(entityTitle, i)
ret = append(ret, &pb.ActionArgumentChoice{ ret = append(ret, &apiv1.ActionArgumentChoice{
Value: sv.ReplaceEntityVars(prefix, firstChoice.Value), Value: sv.ReplaceEntityVars(prefix, firstChoice.Value),
Title: sv.ReplaceEntityVars(prefix, firstChoice.Title), Title: sv.ReplaceEntityVars(prefix, firstChoice.Title),
}) })
@ -92,11 +92,11 @@ func buildChoicesEntity(firstChoice config.ActionArgumentChoice, entityTitle str
return ret return ret
} }
func buildChoicesSimple(choices []config.ActionArgumentChoice) []*pb.ActionArgumentChoice { func buildChoicesSimple(choices []config.ActionArgumentChoice) []*apiv1.ActionArgumentChoice {
ret := []*pb.ActionArgumentChoice{} ret := []*apiv1.ActionArgumentChoice{}
for _, cfgChoice := range choices { for _, cfgChoice := range choices {
pbChoice := pb.ActionArgumentChoice{ pbChoice := apiv1.ActionArgumentChoice{
Value: cfgChoice.Value, Value: cfgChoice.Value,
Title: cfgChoice.Title, Title: cfgChoice.Title,
} }

View File

@ -1,14 +1,14 @@
package grpcapi package grpcapi
import ( import (
pb "github.com/OliveTin/OliveTin/gen/grpc" apiv1 "github.com/OliveTin/OliveTin/gen/grpc/olivetin/api/v1"
config "github.com/OliveTin/OliveTin/internal/config" config "github.com/OliveTin/OliveTin/internal/config"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
func dashboardCfgToPb(res *pb.GetDashboardComponentsResponse, dashboards []*config.DashboardComponent, cfg *config.Config) { func dashboardCfgToPb(res *apiv1.GetDashboardComponentsResponse, dashboards []*config.DashboardComponent, cfg *config.Config) {
for _, dashboard := range dashboards { for _, dashboard := range dashboards {
res.Dashboards = append(res.Dashboards, &pb.DashboardComponent{ res.Dashboards = append(res.Dashboards, &apiv1.DashboardComponent{
Type: "dashboard", Type: "dashboard",
Title: dashboard.Title, Title: dashboard.Title,
Contents: getDashboardComponentContents(dashboard, cfg), Contents: getDashboardComponentContents(dashboard, cfg),
@ -16,8 +16,8 @@ func dashboardCfgToPb(res *pb.GetDashboardComponentsResponse, dashboards []*conf
} }
} }
func getDashboardComponentContents(dashboard *config.DashboardComponent, cfg *config.Config) []*pb.DashboardComponent { func getDashboardComponentContents(dashboard *config.DashboardComponent, cfg *config.Config) []*apiv1.DashboardComponent {
ret := make([]*pb.DashboardComponent, 0) ret := make([]*apiv1.DashboardComponent, 0)
for _, subitem := range dashboard.Contents { for _, subitem := range dashboard.Contents {
if subitem.Type == "fieldset" && subitem.Entity != "" { if subitem.Type == "fieldset" && subitem.Entity != "" {
@ -25,7 +25,7 @@ func getDashboardComponentContents(dashboard *config.DashboardComponent, cfg *co
continue continue
} }
newitem := &pb.DashboardComponent{ newitem := &apiv1.DashboardComponent{
Title: subitem.Title, Title: subitem.Title,
Type: getDashboardComponentType(&subitem), Type: getDashboardComponentType(&subitem),
Contents: getDashboardComponentContents(&subitem, cfg), Contents: getDashboardComponentContents(&subitem, cfg),

View File

@ -1,13 +1,13 @@
package grpcapi package grpcapi
import ( import (
pb "github.com/OliveTin/OliveTin/gen/grpc" apiv1 "github.com/OliveTin/OliveTin/gen/grpc/olivetin/api/v1"
config "github.com/OliveTin/OliveTin/internal/config" config "github.com/OliveTin/OliveTin/internal/config"
sv "github.com/OliveTin/OliveTin/internal/stringvariables" sv "github.com/OliveTin/OliveTin/internal/stringvariables"
) )
func buildEntityFieldsets(entityTitle string, tpl *config.DashboardComponent) []*pb.DashboardComponent { func buildEntityFieldsets(entityTitle string, tpl *config.DashboardComponent) []*apiv1.DashboardComponent {
ret := make([]*pb.DashboardComponent, 0) ret := make([]*apiv1.DashboardComponent, 0)
entityCount := sv.GetEntityCount(entityTitle) entityCount := sv.GetEntityCount(entityTitle)
@ -18,10 +18,10 @@ func buildEntityFieldsets(entityTitle string, tpl *config.DashboardComponent) []
return ret return ret
} }
func buildEntityFieldset(tpl *config.DashboardComponent, entityTitle string, entityIndex int) *pb.DashboardComponent { func buildEntityFieldset(tpl *config.DashboardComponent, entityTitle string, entityIndex int) *apiv1.DashboardComponent {
prefix := sv.GetEntityPrefix(entityTitle, entityIndex) prefix := sv.GetEntityPrefix(entityTitle, entityIndex)
return &pb.DashboardComponent{ return &apiv1.DashboardComponent{
Title: sv.ReplaceEntityVars(prefix, tpl.Title), Title: sv.ReplaceEntityVars(prefix, tpl.Title),
Type: "fieldset", Type: "fieldset",
Contents: buildEntityFieldsetContents(tpl.Contents, prefix), Contents: buildEntityFieldsetContents(tpl.Contents, prefix),
@ -29,11 +29,11 @@ func buildEntityFieldset(tpl *config.DashboardComponent, entityTitle string, ent
} }
} }
func buildEntityFieldsetContents(contents []config.DashboardComponent, prefix string) []*pb.DashboardComponent { func buildEntityFieldsetContents(contents []config.DashboardComponent, prefix string) []*apiv1.DashboardComponent {
ret := make([]*pb.DashboardComponent, 0) ret := make([]*apiv1.DashboardComponent, 0)
for _, subitem := range contents { for _, subitem := range contents {
clone := &pb.DashboardComponent{} clone := &apiv1.DashboardComponent{}
clone.CssClass = sv.ReplaceEntityVars(prefix, subitem.CssClass) clone.CssClass = sv.ReplaceEntityVars(prefix, subitem.CssClass)
if subitem.Type == "" || subitem.Type == "link" { if subitem.Type == "" || subitem.Type == "link" {

View File

@ -12,7 +12,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
pb "github.com/OliveTin/OliveTin/gen/grpc" apiv1 "github.com/OliveTin/OliveTin/gen/grpc/olivetin/api/v1"
config "github.com/OliveTin/OliveTin/internal/config" config "github.com/OliveTin/OliveTin/internal/config"
"github.com/OliveTin/OliveTin/internal/executor" "github.com/OliveTin/OliveTin/internal/executor"
) )
@ -26,7 +26,7 @@ func initServer(cfg *config.Config) *executor.Executor {
lis = bufconn.Listen(bufSize) lis = bufconn.Listen(bufSize)
s := grpc.NewServer() s := grpc.NewServer()
pb.RegisterOliveTinApiServiceServer(s, newServer(ex)) apiv1.RegisterOliveTinApiServiceServer(s, newServer(ex))
go func() { go func() {
if err := s.Serve(lis); err != nil { if err := s.Serve(lis); err != nil {
@ -41,7 +41,7 @@ func bufDialer(context.Context, string) (net.Conn, error) {
return lis.Dial() return lis.Dial()
} }
func getNewTestServerAndClient(t *testing.T, injectedConfig *config.Config) (*grpc.ClientConn, pb.OliveTinApiServiceClient) { func getNewTestServerAndClient(t *testing.T, injectedConfig *config.Config) (*grpc.ClientConn, apiv1.OliveTinApiServiceClient) {
cfg = injectedConfig cfg = injectedConfig
ctx := context.Background() ctx := context.Background()
@ -52,7 +52,7 @@ func getNewTestServerAndClient(t *testing.T, injectedConfig *config.Config) (*gr
t.Fatalf("Failed to dial bufnet: %v", err) t.Fatalf("Failed to dial bufnet: %v", err)
} }
client := pb.NewOliveTinApiServiceClient(conn) client := apiv1.NewOliveTinApiServiceClient(conn)
return conn, client return conn, client
} }
@ -72,7 +72,7 @@ func TestGetActionsAndStart(t *testing.T) {
conn, client := getNewTestServerAndClient(t, cfg) conn, client := getNewTestServerAndClient(t, cfg)
respGb, err := client.GetDashboardComponents(context.Background(), &pb.GetDashboardComponentsRequest{}) respGb, err := client.GetDashboardComponents(context.Background(), &apiv1.GetDashboardComponentsRequest{})
if err != nil { if err != nil {
t.Errorf("GetDashboardComponentsRequest: %v", err) t.Errorf("GetDashboardComponentsRequest: %v", err)
@ -84,7 +84,7 @@ func TestGetActionsAndStart(t *testing.T) {
log.Printf("Response: %+v", respGb) log.Printf("Response: %+v", respGb)
respSa, err := client.StartAction(context.Background(), &pb.StartActionRequest{ActionId: "blat"}) respSa, err := client.StartAction(context.Background(), &apiv1.StartActionRequest{ActionId: "blat"})
assert.Nil(t, err, "Empty err after start action") assert.Nil(t, err, "Empty err after start action")
assert.NotNil(t, respSa, "Empty err after start action") assert.NotNil(t, respSa, "Empty err after start action")

View File

@ -10,7 +10,7 @@ import (
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
"net/http" "net/http"
gw "github.com/OliveTin/OliveTin/gen/grpc" apiv1 "github.com/OliveTin/OliveTin/gen/grpc/olivetin/api/v1"
config "github.com/OliveTin/OliveTin/internal/config" config "github.com/OliveTin/OliveTin/internal/config"
cors "github.com/OliveTin/OliveTin/internal/cors" cors "github.com/OliveTin/OliveTin/internal/cors"
@ -181,7 +181,7 @@ func newMux() *runtime.ServeMux {
opts := []grpc.DialOption{grpc.WithInsecure()} opts := []grpc.DialOption{grpc.WithInsecure()}
err := gw.RegisterOliveTinApiServiceHandlerFromEndpoint(ctx, mux, cfg.ListenAddressGrpcActions, opts) err := apiv1.RegisterOliveTinApiServiceHandlerFromEndpoint(ctx, mux, cfg.ListenAddressGrpcActions, opts)
if err != nil { if err != nil {
log.Panicf("Could not register REST API Handler %v", err) log.Panicf("Could not register REST API Handler %v", err)

View File

@ -4,7 +4,7 @@ import (
"net/http" "net/http"
"sync" "sync"
pb "github.com/OliveTin/OliveTin/gen/grpc" apiv1 "github.com/OliveTin/OliveTin/gen/grpc/olivetin/api/v1"
"github.com/OliveTin/OliveTin/internal/executor" "github.com/OliveTin/OliveTin/internal/executor"
ws "github.com/gorilla/websocket" ws "github.com/gorilla/websocket"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -36,17 +36,17 @@ var ExecutionListener WebsocketExecutionListener
type WebsocketExecutionListener struct{} type WebsocketExecutionListener struct{}
func (WebsocketExecutionListener) OnExecutionStarted(ile *executor.InternalLogEntry) { func (WebsocketExecutionListener) OnExecutionStarted(ile *executor.InternalLogEntry) {
broadcast(&pb.EventExecutionStarted{ broadcast(&apiv1.EventExecutionStarted{
LogEntry: internalLogEntryToPb(ile), LogEntry: internalLogEntryToPb(ile),
}) })
} }
func OnEntityChanged() { func OnEntityChanged() {
broadcast(&pb.EventEntityChanged{}) broadcast(&apiv1.EventEntityChanged{})
} }
func (WebsocketExecutionListener) OnActionMapRebuilt() { func (WebsocketExecutionListener) OnActionMapRebuilt() {
broadcast(&pb.EventConfigChanged{}) broadcast(&apiv1.EventConfigChanged{})
} }
/* /*
@ -69,7 +69,7 @@ func checkOriginPermissive(r *http.Request) bool {
func (WebsocketExecutionListener) OnOutputChunk(chunk []byte, executionTrackingId string) { func (WebsocketExecutionListener) OnOutputChunk(chunk []byte, executionTrackingId string) {
log.Tracef("outputchunk: %s", string(chunk)) log.Tracef("outputchunk: %s", string(chunk))
oc := &pb.EventOutputChunk{ oc := &apiv1.EventOutputChunk{
Output: string(chunk), Output: string(chunk),
ExecutionTrackingId: executionTrackingId, ExecutionTrackingId: executionTrackingId,
} }
@ -78,7 +78,7 @@ func (WebsocketExecutionListener) OnOutputChunk(chunk []byte, executionTrackingI
} }
func (WebsocketExecutionListener) OnExecutionFinished(logEntry *executor.InternalLogEntry) { func (WebsocketExecutionListener) OnExecutionFinished(logEntry *executor.InternalLogEntry) {
evt := &pb.EventExecutionFinished{ evt := &apiv1.EventExecutionFinished{
LogEntry: internalLogEntryToPb(logEntry), LogEntry: internalLogEntryToPb(logEntry),
} }
@ -161,8 +161,8 @@ func HandleWebsocket(w http.ResponseWriter, r *http.Request) bool {
return true return true
} }
func internalLogEntryToPb(logEntry *executor.InternalLogEntry) *pb.LogEntry { func internalLogEntryToPb(logEntry *executor.InternalLogEntry) *apiv1.LogEntry {
return &pb.LogEntry{ return &apiv1.LogEntry{
ActionTitle: logEntry.ActionTitle, ActionTitle: logEntry.ActionTitle,
ActionIcon: logEntry.ActionIcon, ActionIcon: logEntry.ActionIcon,
ActionId: logEntry.ActionId, ActionId: logEntry.ActionId,

4
proto/Makefile Normal file
View File

@ -0,0 +1,4 @@
buf:
buf generate
.PHONY: buf

View File

@ -1,15 +1,15 @@
version: v1 version: v1
plugins: plugins:
- name: go - name: go
out: gen/grpc/ out: ../gen/grpc/
opt: paths=source_relative opt: paths=source_relative
- name: go-grpc - name: go-grpc
out: gen/grpc/ out: ../gen/grpc/
opt: paths=source_relative,require_unimplemented_servers=false opt: paths=source_relative,require_unimplemented_servers=false
- name: grpc-gateway - name: grpc-gateway
out: gen/grpc/ out: ../gen/grpc/
opt: paths=source_relative opt: paths=source_relative
# - name: swagger # - name: swagger

6
proto/buf.lock Normal file
View File

@ -0,0 +1,6 @@
# Generated by buf. DO NOT EDIT.
version: v2
deps:
- name: buf.build/googleapis/googleapis
commit: 751cbe31638d43a9bfb6162cd2352e67
digest: b5:51ba5c31f244fd74420f0e66d13f2b5dd6024dcfe1a29dc45bd8f6e61c1444c828b9add9e7dd25a4513ebbee8097a970e0712a2e2cd955c2d60cf8905204f51a

View File

@ -1,10 +1,9 @@
version: v1 version: v2
deps: deps:
- buf.build/googleapis/googleapis - buf.build/googleapis/googleapis
lint: lint:
use: use:
- DEFAULT - STANDARD
build:
breaking: breaking:
use: use:
- FILE - FILE

View File

@ -1,6 +1,8 @@
syntax = "proto3"; syntax = "proto3";
option go_package = "gen/grpc"; package olivetin.api.v1;
option go_package = "github.com/jamesread/OliveTin/gen/grpc/olivetin/api/v1;apiv1";
import "google/api/annotations.proto"; import "google/api/annotations.proto";
import "google/api/httpbody.proto"; import "google/api/httpbody.proto";

View File

@ -46,6 +46,7 @@ function websocketOnOpen (evt) {
function websocketOnMessage (msg) { function websocketOnMessage (msg) {
// FIXME check msg status is OK // FIXME check msg status is OK
const j = JSON.parse(msg.data) const j = JSON.parse(msg.data)
j.type = j.type.replace('olivetin.api.v1.', '')
const e = new Event(j.type) const e = new Event(j.type)
e.payload = j.payload e.payload = j.payload