Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package govc for openSUSE:Factory checked in at 2026-10-28 17:49:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/govc (Old) and /work/SRC/openSUSE:Factory/.govc.new.2252680 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "govc" Wed Oct 28 17:49:03 2026 rev:36 rq:1393392 version:0.56.2 Changes: -------- --- /work/SRC/openSUSE:Factory/govc/govc.changes 2026-08-28 19:58:53.010098885 +0200 +++ /work/SRC/openSUSE:Factory/.govc.new.2252680/govc.changes 2026-10-28 17:49:15.932888133 +0100 @@ -1,0 +2,23 @@ +Wed Oct 28 06:07:12 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.56.2: + * Fix + - [c128513] return error from toolbox Run if process not found + (#4149) + * Chore + - [10a792c] Update version.go for v0.56.2 + - [b4dd7a8] use setup-go with check-latest + - [2db454e] output go version with release dryrun + * Commits + - [10a792c] chore: Update version.go for v0.56.2 + - [b4dd7a8] chore: use setup-go with check-latest + - [2db454e] chore: output go version with release dryrun + - [c128513] fix: return error from toolbox Run if process not + found (#4149) +- Update to version 0.56.1: + * Chore + - [e45bf1c] Update version.go for v0.56.1 + * Commits + - [e45bf1c] chore: Update version.go for v0.56.1 + +------------------------------------------------------------------- Old: ---- govc-0.56.0.obscpio New: ---- govc-0.56.2.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ govc.spec ++++++ --- /var/tmp/diff_new_pack.b82Tne/_old 2026-10-28 17:49:18.042976763 +0100 +++ /var/tmp/diff_new_pack.b82Tne/_new 2026-10-28 17:49:18.048977016 +0100 @@ -17,7 +17,7 @@ Name: govc -Version: 0.56.0 +Version: 0.56.2 Release: 0 Summary: vSphere CLI built on top of govmomi License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.b82Tne/_old 2026-10-28 17:49:18.150981300 +0100 +++ /var/tmp/diff_new_pack.b82Tne/_new 2026-10-28 17:49:18.155981510 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/vmware/govmomi.git</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">refs/tags/v0.56.0</param> + <param name="revision">refs/tags/v0.56.2</param> <param name="match-tag">v*</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.b82Tne/_old 2026-10-28 17:49:18.209983778 +0100 +++ /var/tmp/diff_new_pack.b82Tne/_new 2026-10-28 17:49:18.217984114 +0100 @@ -3,6 +3,6 @@ <param name="url">https://github.com/vmware/govmomi</param> <param name="changesrevision">df7c057af6c06430955ce56d6f04b7e49138f9b3</param></service><service name="tar_scm"> <param name="url">https://github.com/vmware/govmomi.git</param> - <param name="changesrevision">81608f9b9725d64e4ed447b9a338c9f03dbf8840</param></service></servicedata> + <param name="changesrevision">10a792caabf08426f90d2e58d4a3a41b0a427c0b</param></service></servicedata> (No newline at EOF) ++++++ govc-0.56.0.obscpio -> govc-0.56.2.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/govc-0.56.0/guest/toolbox/client.go new/govc-0.56.2/guest/toolbox/client.go --- old/govc-0.56.0/guest/toolbox/client.go 2026-08-21 05:44:51.000000000 +0200 +++ new/govc-0.56.2/guest/toolbox/client.go 2026-10-26 20:28:46.000000000 +0100 @@ -7,6 +7,7 @@ import ( "bytes" "context" + "errors" "fmt" "io" "log" @@ -84,6 +85,10 @@ return c.FileManager.CreateTemporaryFile(ctx, c.Authentication, "govmomi-", "", "") } +// ErrProcessNotFound is returned by Run when the guest does not report the process that was started, +// such as after VMware Tools was restarted. +var ErrProcessNotFound = errors.New("process not found in guest") + type exitError struct { error exitCode int @@ -94,6 +99,9 @@ } // Run implements exec.Cmd.Run over vmx guest RPC against standard vmware-tools or toolbox. +// If the guest stops reporting the started process, Run returns an error wrapping ErrProcessNotFound. +// The command was started and may have completed, so its outcome is unknown +// and it should only be run again if it is safe to do so. func (c *Client) Run(ctx context.Context, cmd *exec.Cmd) error { if cmd.Stdin != nil { dst, err := c.mktemp(ctx) @@ -183,6 +191,12 @@ return err } + if len(procs) == 0 { + // The guest no longer knows about the process, + // such as after VMware Tools was restarted. + return fmt.Errorf("%s: pid %d: %w", cmd.Path, pid, ErrProcessNotFound) + } + p := procs[0] if p.EndTime == nil { <-time.After(time.Second / 2) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/govc-0.56.0/guest/toolbox/client_test.go new/govc-0.56.2/guest/toolbox/client_test.go --- old/govc-0.56.0/guest/toolbox/client_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/govc-0.56.2/guest/toolbox/client_test.go 2026-10-26 20:28:46.000000000 +0100 @@ -0,0 +1,160 @@ +// © Broadcom. All Rights Reserved. +// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. +// SPDX-License-Identifier: Apache-2.0 + +package toolbox_test + +import ( + "context" + "errors" + "os/exec" + "slices" + "testing" + "time" + + "github.com/vmware/govmomi/guest/toolbox" + "github.com/vmware/govmomi/simulator" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +const testPid = 42 + +// guestOps fakes the StartProgramInGuest and ListProcessesInGuest responses, +// as vcsim can only start guest processes in a docker container. +// Each ListProcessesInGuest call pops the next entry from lists, +// and returns an empty list once lists is exhausted. +// The pids of each ListProcessesInGuest request are recorded in polled. +type guestOps struct { + soap.RoundTripper + + lists [][]types.GuestProcessInfo + polled [][]int64 +} + +func (g *guestOps) RoundTrip(ctx context.Context, req, res soap.HasFault) error { + switch req := req.(type) { + case *methods.StartProgramInGuestBody: + res.(*methods.StartProgramInGuestBody).Res = &types.StartProgramInGuestResponse{ + Returnval: testPid, + } + return nil + case *methods.ListProcessesInGuestBody: + g.polled = append(g.polled, req.Req.Pids) + + var procs []types.GuestProcessInfo + if len(g.lists) != 0 { + procs, g.lists = g.lists[0], g.lists[1:] + } + + res.(*methods.ListProcessesInGuestBody).Res = &types.ListProcessesInGuestResponse{ + Returnval: procs, + } + return nil + } + + return g.RoundTripper.RoundTrip(ctx, req, res) +} + +func TestClientRun(t *testing.T) { + end := types.NewTime(time.Now()) + + tests := []struct { + name string + lists [][]types.GuestProcessInfo + polls int // expected number of ListProcessesInGuest calls + wantErr error // expected error, matched with errors.Is + wantCode int // expected exit code, if non-zero + }{ + { + name: "exit 0", + lists: [][]types.GuestProcessInfo{{{Pid: testPid, EndTime: end}}}, + polls: 1, + }, + { + name: "exit 3", + lists: [][]types.GuestProcessInfo{{{Pid: testPid, EndTime: end, ExitCode: 3}}}, + polls: 1, + wantCode: 3, + }, + { + name: "poll until exit", + lists: [][]types.GuestProcessInfo{ + {{Pid: testPid}}, + {{Pid: testPid, EndTime: end}}, + }, + polls: 2, + }, + { + // The guest no longer knows the pid, such as after a vmtoolsd restart. + // ListProcessesInGuest succeeds with an empty list in this case. + name: "process not found", + polls: 1, + wantErr: toolbox.ErrProcessNotFound, + }, + { + name: "process not found while polling", + lists: [][]types.GuestProcessInfo{ + {{Pid: testPid}}, + }, + polls: 2, + wantErr: toolbox.ErrProcessNotFound, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + simulator.Test(func(ctx context.Context, c *vim25.Client) { + vm := simulator.Map(ctx).Any("VirtualMachine").(*simulator.VirtualMachine) + + ops := &guestOps{RoundTripper: c.RoundTripper, lists: test.lists} + c.RoundTripper = ops + + tools, err := toolbox.NewClient(ctx, c, vm, &types.NamePasswordAuthentication{ + Username: "user", + Password: "pass", + }) + if err != nil { + t.Fatal(err) + } + + err = tools.Run(ctx, &exec.Cmd{Path: "/bin/true"}) + + if len(ops.polled) != test.polls { + t.Errorf("ListProcessesInGuest called %d times, expected %d", len(ops.polled), test.polls) + } + for _, pids := range ops.polled { + if !slices.Equal(pids, []int64{testPid}) { + t.Errorf("ListProcessesInGuest pids=%v, expected [%d]", pids, testPid) + } + } + + var ee interface{ ExitCode() int } + isExit := errors.As(err, &ee) + + switch { + case test.wantErr != nil: + if !errors.Is(err, test.wantErr) { + t.Fatalf("error=%v, expected %v", err, test.wantErr) + } + if isExit { + t.Errorf("unexpected exit error: %s", err) + } + case test.wantCode != 0: + if !isExit { + t.Fatalf("expected an exit error, got: %v", err) + } + if ee.ExitCode() != test.wantCode { + t.Errorf("exit code=%d, expected %d", ee.ExitCode(), test.wantCode) + } + default: + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + } + }) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/govc-0.56.0/internal/version/version.go new/govc-0.56.2/internal/version/version.go --- old/govc-0.56.0/internal/version/version.go 2026-08-21 05:44:51.000000000 +0200 +++ new/govc-0.56.2/internal/version/version.go 2026-10-26 20:28:46.000000000 +0100 @@ -9,5 +9,5 @@ ClientName = "govmomi" // ClientVersion is the version of this SDK - ClientVersion = "0.56.0" + ClientVersion = "0.56.2" ) ++++++ govc.obsinfo ++++++ --- /var/tmp/diff_new_pack.b82Tne/_old 2026-10-28 17:49:20.830093830 +0100 +++ /var/tmp/diff_new_pack.b82Tne/_new 2026-10-28 17:49:20.834093998 +0100 @@ -1,5 +1,5 @@ name: govc -version: 0.56.0 -mtime: 1787283891 -commit: 81608f9b9725d64e4ed447b9a338c9f03dbf8840 +version: 0.56.2 +mtime: 1793042926 +commit: 10a792caabf08426f90d2e58d4a3a41b0a427c0b ++++++ vendor.tar.gz ++++++
