feat: backend executor implement
This commit is contained in:
@@ -25,6 +25,7 @@ const maximumRequestBytes = 1 << 20
|
||||
type backendUpdater interface {
|
||||
UpdateRepack(context.Context, string, backendupdate.ProgressReporter) (transaction.Transaction, error)
|
||||
UpdateNativeJAR(context.Context, string, backendupdate.ProgressReporter) (transaction.Transaction, error)
|
||||
UpdateContainerImage(context.Context, string, backendupdate.ProgressReporter) (transaction.Transaction, error)
|
||||
Restart(context.Context, backendupdate.ProgressReporter) (transaction.Transaction, error)
|
||||
}
|
||||
|
||||
@@ -124,15 +125,29 @@ func (s *Server) handle(ctx context.Context, connection net.Conn) {
|
||||
case daemonapi.OperationUpdate:
|
||||
switch request.InputType {
|
||||
case daemonapi.InputTypeRepackZIP:
|
||||
if request.File == "" || request.ImageReference != "" {
|
||||
_ = s.writeResponse(connection, daemonapi.Response{Kind: daemonapi.ResponseResult, Error: "repack-zip requires file and does not accept imageReference"})
|
||||
return
|
||||
}
|
||||
record, updateErr = s.updater.UpdateRepack(ctx, request.File, report)
|
||||
case daemonapi.InputTypeNativeJAR:
|
||||
if request.File == "" || request.ImageReference != "" {
|
||||
_ = s.writeResponse(connection, daemonapi.Response{Kind: daemonapi.ResponseResult, Error: "native-jar requires file and does not accept imageReference"})
|
||||
return
|
||||
}
|
||||
record, updateErr = s.updater.UpdateNativeJAR(ctx, request.File, report)
|
||||
case daemonapi.InputTypeContainerImage:
|
||||
if request.File != "" || request.ImageReference == "" {
|
||||
_ = s.writeResponse(connection, daemonapi.Response{Kind: daemonapi.ResponseResult, Error: "container-image requires imageReference and does not accept file"})
|
||||
return
|
||||
}
|
||||
record, updateErr = s.updater.UpdateContainerImage(ctx, request.ImageReference, report)
|
||||
default:
|
||||
_ = s.writeResponse(connection, daemonapi.Response{Kind: daemonapi.ResponseResult, Error: "inputType must be repack-zip or native-jar"})
|
||||
_ = s.writeResponse(connection, daemonapi.Response{Kind: daemonapi.ResponseResult, Error: "inputType must be repack-zip, native-jar, or container-image"})
|
||||
return
|
||||
}
|
||||
case daemonapi.OperationRestart:
|
||||
if request.InputType != "" || request.File != "" {
|
||||
if request.InputType != "" || request.File != "" || request.ImageReference != "" {
|
||||
_ = s.writeResponse(connection, daemonapi.Response{Kind: daemonapi.ResponseResult, Error: "restart does not accept inputType or file"})
|
||||
return
|
||||
}
|
||||
@@ -172,7 +187,7 @@ func decodeRequest(reader io.Reader) (daemonapi.Request, error) {
|
||||
}
|
||||
return daemonapi.Request{}, fmt.Errorf("decode daemon request trailing content: %w", err)
|
||||
}
|
||||
if strings.TrimSpace(request.Operation) != request.Operation || strings.TrimSpace(request.Service) != request.Service || strings.TrimSpace(request.InputType) != request.InputType || strings.TrimSpace(request.File) != request.File {
|
||||
if strings.TrimSpace(request.Operation) != request.Operation || strings.TrimSpace(request.Service) != request.Service || strings.TrimSpace(request.InputType) != request.InputType || strings.TrimSpace(request.File) != request.File || strings.TrimSpace(request.ImageReference) != request.ImageReference {
|
||||
return daemonapi.Request{}, errors.New("daemon request fields must not contain surrounding whitespace")
|
||||
}
|
||||
return request, nil
|
||||
|
||||
@@ -84,6 +84,29 @@ func TestServerAcceptsDirectNativeJARThroughUnixSocket(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerAcceptsContainerImageThroughUnixSocket(t *testing.T) {
|
||||
socketPath := shortSocketPath(t)
|
||||
updater := &fakeUpdater{record: transaction.Transaction{ID: "transaction-container-01", State: transaction.StateCommitted}}
|
||||
server, err := New(socketPath, updater, slog.New(slog.NewTextHandler(io.Discard, nil)))
|
||||
if err != nil {
|
||||
t.Fatalf("create daemon server: %v", err)
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
serveResult := make(chan error, 1)
|
||||
go func() { serveResult <- server.Serve(ctx) }()
|
||||
waitForSocket(t, socketPath, serveResult)
|
||||
|
||||
imageReference := "harbor.ymswell.asia/ymswell/glory-ymswell:20260813-184902-a37bf50d-v1.1.8.1"
|
||||
response, err := daemonclient.UpdateContainerImage(context.Background(), socketPath, "backend", imageReference, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("submit container backend image: %v", err)
|
||||
}
|
||||
if response.TransactionID != updater.record.ID || updater.file != imageReference || updater.inputType != daemonapi.InputTypeContainerImage {
|
||||
t.Fatalf("unexpected container update dispatch: response=%+v image=%s inputType=%s", response, updater.file, updater.inputType)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerReturnsTransactionFailure(t *testing.T) {
|
||||
socketPath := shortSocketPath(t)
|
||||
updater := &fakeUpdater{
|
||||
@@ -194,6 +217,16 @@ func (u *fakeUpdater) UpdateNativeJAR(_ context.Context, file string, report bac
|
||||
return u.record, u.err
|
||||
}
|
||||
|
||||
func (u *fakeUpdater) UpdateContainerImage(_ context.Context, imageReference string, report backendupdate.ProgressReporter) (transaction.Transaction, error) {
|
||||
u.file = imageReference
|
||||
u.inputType = daemonapi.InputTypeContainerImage
|
||||
u.operation = daemonapi.OperationUpdate
|
||||
if report != nil {
|
||||
report(backendupdate.Progress{TransactionID: u.record.ID, State: transaction.StateStarting, Message: "test update progress"})
|
||||
}
|
||||
return u.record, u.err
|
||||
}
|
||||
|
||||
func (u *fakeUpdater) Restart(_ context.Context, report backendupdate.ProgressReporter) (transaction.Transaction, error) {
|
||||
u.operation = daemonapi.OperationRestart
|
||||
if report != nil {
|
||||
|
||||
Reference in New Issue
Block a user