Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package google-guest-agent for 
openSUSE:Factory checked in at 2026-10-23 20:31:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/google-guest-agent (Old)
 and      /work/SRC/openSUSE:Factory/.google-guest-agent.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "google-guest-agent"

Fri Oct 23 20:31:19 2026 rev:72 rq:1392072 version:20261015.00

Changes:
--------
--- /work/SRC/openSUSE:Factory/google-guest-agent/google-guest-agent.changes    
2026-09-22 15:50:40.541891619 +0200
+++ 
/work/SRC/openSUSE:Factory/.google-guest-agent.new.2252680/google-guest-agent.changes
       2026-10-23 20:33:23.332372549 +0200
@@ -1,0 +2,13 @@
+Tue Oct 20 12:33:20 UTC 2026 - Robert Schweikert <[email protected]>
+
+- Ship gce-workload-cert-refresh.timer (bsc#1273192)
+
+-------------------------------------------------------------------
+Fri Oct 16 08:55:41 UTC 2026 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to version 20261015.00
+  * Wait for new account to become visible before adding to groups (#635)
+- Update golang.org/x/crypto to v0.58.0
+- Update golang.org/x/net to v0.61.0 (bsc#1285283, CVE-2026-78669)
+
+-------------------------------------------------------------------
@@ -35 +47,0 @@
-- Ship gce-workload-cert-refresh.timer (bsc#1273192)

Old:
----
  guest-agent-20260917.00.tar.gz

New:
----
  guest-agent-20261015.00.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ google-guest-agent.spec ++++++
--- /var/tmp/diff_new_pack.dyAXVs/_old  2026-10-23 20:33:24.123405649 +0200
+++ /var/tmp/diff_new_pack.dyAXVs/_new  2026-10-23 20:33:24.125405732 +0200
@@ -1,6 +1,7 @@
 #
 # spec file for package google-guest-agent
 #
+# Copyright (c) 2026 SUSE LLC
 # Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
@@ -19,7 +20,7 @@
 %define shortname guest-agent
 
 Name:           google-guest-agent
-Version:        20260917.00
+Version:        20261015.00
 Release:        0
 Summary:        Google Cloud Guest Agent
 License:        Apache-2.0
@@ -66,6 +67,7 @@
 install -p -m 0644 google-startup-scripts.service %{buildroot}%{_unitdir}
 install -p -m 0644 google-shutdown-scripts.service %{buildroot}%{_unitdir}
 install -p -m 0644 gce-workload-cert-refresh.service %{buildroot}%{_unitdir}
+install -p -m 0644 gce-workload-cert-refresh.timer %{buildroot}%{_unitdir}
 mkdir -p %{buildroot}%{_sbindir}
 for srv_name in %{buildroot}%{_unitdir}/*.service; do rc_name=$(basename -s 
'.service' $srv_name); ln -s service %{buildroot}%{_sbindir}/rc$rc_name; done
 

++++++ _service ++++++
--- /var/tmp/diff_new_pack.dyAXVs/_old  2026-10-23 20:33:24.162407281 +0200
+++ /var/tmp/diff_new_pack.dyAXVs/_new  2026-10-23 20:33:24.165407406 +0200
@@ -3,8 +3,8 @@
     <param 
name="url">https://github.com/GoogleCloudPlatform/guest-agent/</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="versionformat">20260917.00</param>
-    <param name="revision">20260917.00</param>
+    <param name="versionformat">20261015.00</param>
+    <param name="revision">20261015.00</param>
     <param name="changesgenerate">enable</param>
   </service>
   <service name="recompress" mode="disabled">
@@ -15,8 +15,9 @@
     <param name="basename">guest-agent</param>
   </service>
   <service name="go_modules" mode="disabled">
-    <param name="archive">guest-agent-20260917.00.tar.gz</param>
-    <param 
name="replace">golang.org/x/crypto=golang.org/x/[email protected]</param>
+    <param name="archive">guest-agent-20261015.00.tar.gz</param>
+    <param 
name="replace">golang.org/x/crypto=golang.org/x/[email protected]</param>
+    <param name="replace">golang.org/x/net=golang.org/x/[email protected]</param>
   </service>
 </services>
 

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.dyAXVs/_old  2026-10-23 20:33:24.188408369 +0200
+++ /var/tmp/diff_new_pack.dyAXVs/_new  2026-10-23 20:33:24.192408536 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/GoogleCloudPlatform/guest-agent/</param>
-              <param 
name="changesrevision">9c6ad8833a3ac64f49b735844b29f5ea1f9357c5</param></service></servicedata>
+              <param 
name="changesrevision">778f752c2994d5ab69550941cea901bd43f76be7</param></service></servicedata>
 (No newline at EOF)
 

++++++ guest-agent-20260917.00.tar.gz -> guest-agent-20261015.00.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20260917.00/google_guest_agent/non_windows_accounts.go 
new/guest-agent-20261015.00/google_guest_agent/non_windows_accounts.go
--- old/guest-agent-20260917.00/google_guest_agent/non_windows_accounts.go      
2026-09-18 01:05:23.000000000 +0200
+++ new/guest-agent-20261015.00/google_guest_agent/non_windows_accounts.go      
2026-09-23 16:43:12.000000000 +0200
@@ -28,6 +28,7 @@
        "sort"
        "strconv"
        "strings"
+       "time"
 
        "github.com/GoogleCloudPlatform/guest-agent/google_guest_agent/cfg"
        "github.com/GoogleCloudPlatform/guest-agent/google_guest_agent/run"
@@ -356,6 +357,17 @@
        if err := createUser(ctx, user, uid, gid); err != nil {
                return err
        }
+
+       // The account database (e.g. an NSS cache such as nscd) is not always
+       // consistent with the just-run useradd immediately; on a busy or
+       // just-booted system a lookup for the new user can transiently fail,
+       // which in turn makes the gpasswd calls below fail with "user does not
+       // exist" even though useradd succeeded. Wait for the account to
+       // actually resolve before touching group membership.
+       if err := waitForUserVisible(ctx, user); err != nil {
+               return fmt.Errorf("user %s was created but did not become 
visible: %v", user, err)
+       }
+
        groups := config.Accounts.Groups
        for _, group := range strings.Split(groups, ",") {
                addUserToGroup(ctx, user, group)
@@ -363,6 +375,47 @@
        return addUserToGroup(ctx, user, "google-sudoers")
 }
 
+// userExistsFunc is a seam for testing waitForUserVisible without touching
+// the real user database.
+var userExistsFunc = userExists
+
+// userVisiblePollInterval and userVisiblePollAttempts bound how long
+// waitForUserVisible will wait for a freshly created account to become
+// visible. Five attempts at 200ms cover the nscd-restart window observed in
+// practice while keeping worst case added boot latency small (~1s).
+var (
+       userVisiblePollInterval = 200 * time.Millisecond
+       userVisiblePollAttempts = 5
+)
+
+// waitForUserVisible polls userExistsFunc until it reports the account
+// exists, up to userVisiblePollAttempts times, sleeping
+// userVisiblePollInterval between attempts. It returns nil as soon as the
+// user is visible, or the last error/state seen if it never becomes visible
+// or ctx is done first.
+func waitForUserVisible(ctx context.Context, user string) error {
+       var lastErr error
+       for attempt := 0; attempt < userVisiblePollAttempts; attempt++ {
+               exists, err := userExistsFunc(user)
+               if exists {
+                       return nil
+               }
+               lastErr = err
+               if attempt == userVisiblePollAttempts-1 {
+                       break
+               }
+               select {
+               case <-ctx.Done():
+                       return ctx.Err()
+               case <-time.After(userVisiblePollInterval):
+               }
+       }
+       if lastErr == nil {
+               lastErr = fmt.Errorf("user lookup did not succeed")
+       }
+       return lastErr
+}
+
 // removeGoogleUser removes Google managed users. If deprovision_remove is 
true, the
 // user and its home directory are removed. Otherwise, SSH keys and sudoer
 // permissions are removed but the user remains on the system. Group membership
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20260917.00/google_guest_agent/non_windows_accounts_test.go 
new/guest-agent-20261015.00/google_guest_agent/non_windows_accounts_test.go
--- old/guest-agent-20260917.00/google_guest_agent/non_windows_accounts_test.go 
1970-01-01 01:00:00.000000000 +0100
+++ new/guest-agent-20261015.00/google_guest_agent/non_windows_accounts_test.go 
2026-09-23 16:43:12.000000000 +0200
@@ -0,0 +1,123 @@
+// Copyright 2026 Google LLC
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     https://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build !windows
+
+package main
+
+import (
+       "context"
+       "errors"
+       "testing"
+       "time"
+)
+
+// withStubUserExists replaces userExistsFunc for the duration of a test and
+// restores it afterwards.
+func withStubUserExists(t *testing.T, stub func(string) (bool, error)) {
+       t.Helper()
+       orig := userExistsFunc
+       userExistsFunc = stub
+       t.Cleanup(func() { userExistsFunc = orig })
+}
+
+// withFastPolling shrinks the poll interval so tests don't have to wait out
+// the real production backoff, and restores the original values afterwards.
+func withFastPolling(t *testing.T, attempts int) {
+       t.Helper()
+       origInterval, origAttempts := userVisiblePollInterval, 
userVisiblePollAttempts
+       userVisiblePollInterval = time.Millisecond
+       userVisiblePollAttempts = attempts
+       t.Cleanup(func() {
+               userVisiblePollInterval = origInterval
+               userVisiblePollAttempts = origAttempts
+       })
+}
+
+func TestWaitForUserVisibleImmediateSuccess(t *testing.T) {
+       calls := 0
+       withStubUserExists(t, func(string) (bool, error) {
+               calls++
+               return true, nil
+       })
+       withFastPolling(t, 5)
+
+       if err := waitForUserVisible(context.Background(), "testuser"); err != 
nil {
+               t.Fatalf("waitForUserVisible() = %v, want nil", err)
+       }
+       if calls != 1 {
+               t.Errorf("userExistsFunc called %d times, want 1 (no retry 
needed)", calls)
+       }
+}
+
+func TestWaitForUserVisibleEventualSuccess(t *testing.T) {
+       calls := 0
+       withStubUserExists(t, func(string) (bool, error) {
+               calls++
+               if calls < 3 {
+                       // Mirrors the observed nscd race: the account was just
+                       // created but a lookup transiently reports it missing.
+                       return false, errors.New("user: unknown user testuser")
+               }
+               return true, nil
+       })
+       withFastPolling(t, 5)
+
+       if err := waitForUserVisible(context.Background(), "testuser"); err != 
nil {
+               t.Fatalf("waitForUserVisible() = %v, want nil", err)
+       }
+       if calls != 3 {
+               t.Errorf("userExistsFunc called %d times, want 3", calls)
+       }
+}
+
+func TestWaitForUserVisibleNeverVisible(t *testing.T) {
+       calls := 0
+       wantErr := errors.New("user: unknown user testuser")
+       withStubUserExists(t, func(string) (bool, error) {
+               calls++
+               return false, wantErr
+       })
+       withFastPolling(t, 4)
+
+       err := waitForUserVisible(context.Background(), "testuser")
+       if err == nil {
+               t.Fatal("waitForUserVisible() = nil, want error")
+       }
+       if calls != 4 {
+               t.Errorf("userExistsFunc called %d times, want 4 
(userVisiblePollAttempts)", calls)
+       }
+}
+
+func TestWaitForUserVisibleContextCancelled(t *testing.T) {
+       withStubUserExists(t, func(string) (bool, error) {
+               return false, errors.New("not yet")
+       })
+       withFastPolling(t, 5)
+       // Use a real (tiny) interval so the context has something to race
+       // against, otherwise the immediate Done() would be indistinguishable
+       // from a slow stub.
+       userVisiblePollInterval = 50 * time.Millisecond
+
+       ctx, cancel := context.WithCancel(context.Background())
+       go func() {
+               time.Sleep(10 * time.Millisecond)
+               cancel()
+       }()
+
+       err := waitForUserVisible(ctx, "testuser")
+       if !errors.Is(err, context.Canceled) {
+               t.Fatalf("waitForUserVisible() = %v, want context.Canceled", 
err)
+       }
+}

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/google-guest-agent/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.google-guest-agent.new.2252680/vendor.tar.gz 
differ: char 22, line 1

Reply via email to