Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package skupper for openSUSE:Factory checked 
in at 2025-01-09 15:11:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/skupper (Old)
 and      /work/SRC/openSUSE:Factory/.skupper.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "skupper"

Thu Jan  9 15:11:42 2025 rev:4 rq:1236091 version:1.8.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/skupper/skupper.changes  2024-11-05 
15:41:19.394835615 +0100
+++ /work/SRC/openSUSE:Factory/.skupper.new.1881/skupper.changes        
2025-01-09 15:12:28.972854989 +0100
@@ -1,0 +2,11 @@
+Thu Jan 09 06:39:58 UTC 2025 - opensuse_buildserv...@ojkastl.de
+
+- Update to version 1.8.3:
+  * update for 1.8.3
+  * remove external process log (#1865)
+  * Fixes internal console-auth implementation (#1833)
+  * Ensure podman service containers bind correct hosts (#1799)
+  * Update test images for ARM and OCP 3.11 (#1652)
+  * Add stability to TestGateway and TestBasic tests (#1766)
+
+-------------------------------------------------------------------

Old:
----
  skupper-1.8.2.obscpio

New:
----
  skupper-1.8.3.obscpio

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

Other differences:
------------------
++++++ skupper.spec ++++++
--- /var/tmp/diff_new_pack.VH5S0Z/_old  2025-01-09 15:12:31.024939992 +0100
+++ /var/tmp/diff_new_pack.VH5S0Z/_new  2025-01-09 15:12:31.064941649 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package skupper
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2025 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %define __arch_install_post export NO_BRP_STRIP_DEBUG=true
 
 Name:           skupper
-Version:        1.8.2
+Version:        1.8.3
 Release:        0
 Summary:        Virtual Application Network, enabling rich hybrid cloud 
communication
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.VH5S0Z/_old  2025-01-09 15:12:31.576962859 +0100
+++ /var/tmp/diff_new_pack.VH5S0Z/_new  2025-01-09 15:12:31.616964516 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/skupperproject/skupper</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">1.8.2</param>
+    <param name="revision">1.8.3</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
   </service>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.VH5S0Z/_old  2025-01-09 15:12:31.800972138 +0100
+++ /var/tmp/diff_new_pack.VH5S0Z/_new  2025-01-09 15:12:31.828973297 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/skupperproject/skupper</param>
-              <param 
name="changesrevision">149f4a5588c532d6ab1fc489b19ca24633e521e7</param></service></servicedata>
+              <param 
name="changesrevision">f9c88e4e90f0a7f916e9b5d29e8dce5d2340f78e</param></service></servicedata>
 (No newline at EOF)
 

++++++ generated.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/client/generated/libpod/client/containers/container_rename_libpod_parameters.go
 
new/client/generated/libpod/client/containers/container_rename_libpod_parameters.go
--- 
old/client/generated/libpod/client/containers/container_rename_libpod_parameters.go
 2024-11-04 21:06:38.431534035 +0100
+++ 
new/client/generated/libpod/client/containers/container_rename_libpod_parameters.go
 2025-01-09 07:40:40.545883570 +0100
@@ -63,15 +63,15 @@
 
        /* Name.
 
-          New name for the container
+          Full or partial ID or full name of the container to rename
        */
-       QueryName string
+       PathName string
 
        /* Name.
 
-          Full or partial ID or full name of the container to rename
+          New name for the container
        */
-       PathName string
+       QueryName string
 
        timeout    time.Duration
        Context    context.Context
@@ -126,17 +126,6 @@
        o.HTTPClient = client
 }
 
-// WithQueryName adds the name to the container rename libpod params
-func (o *ContainerRenameLibpodParams) WithQueryName(name string) 
*ContainerRenameLibpodParams {
-       o.SetQueryName(name)
-       return o
-}
-
-// SetQueryName adds the name to the container rename libpod params
-func (o *ContainerRenameLibpodParams) SetQueryName(name string) {
-       o.QueryName = name
-}
-
 // WithPathName adds the name to the container rename libpod params
 func (o *ContainerRenameLibpodParams) WithPathName(name string) 
*ContainerRenameLibpodParams {
        o.SetPathName(name)
@@ -148,6 +137,17 @@
        o.PathName = name
 }
 
+// WithQueryName adds the name to the container rename libpod params
+func (o *ContainerRenameLibpodParams) WithQueryName(name string) 
*ContainerRenameLibpodParams {
+       o.SetQueryName(name)
+       return o
+}
+
+// SetQueryName adds the name to the container rename libpod params
+func (o *ContainerRenameLibpodParams) SetQueryName(name string) {
+       o.QueryName = name
+}
+
 // WriteToRequest writes these params to a swagger request
 func (o *ContainerRenameLibpodParams) WriteToRequest(r runtime.ClientRequest, 
reg strfmt.Registry) error {
 
@@ -156,6 +156,11 @@
        }
        var res []error
 
+       // path param name
+       if err := r.SetPathParam("name", o.PathName); err != nil {
+               return err
+       }
+
        // query param name
        qrName := o.QueryName
        qName := qrName
@@ -166,11 +171,6 @@
                }
        }
 
-       // path param name
-       if err := r.SetPathParam("name", o.PathName); err != nil {
-               return err
-       }
-
        if len(res) > 0 {
                return errors.CompositeValidationError(res...)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/client/generated/libpod/client/containers/container_restore_libpod_parameters.go
 
new/client/generated/libpod/client/containers/container_restore_libpod_parameters.go
--- 
old/client/generated/libpod/client/containers/container_restore_libpod_parameters.go
        2024-11-04 21:06:39.874846900 +0100
+++ 
new/client/generated/libpod/client/containers/container_restore_libpod_parameters.go
        2025-01-09 07:40:40.639217090 +0100
@@ -100,15 +100,15 @@
 
        /* Name.
 
-          the name of the container when restored from a tar. can only be used 
with import
+          the name or id of the container
        */
-       QueryName *string
+       PathName string
 
        /* Name.
 
-          the name or id of the container
+          the name of the container when restored from a tar. can only be used 
with import
        */
-       PathName string
+       QueryName *string
 
        /* PrintStats.
 
@@ -241,17 +241,6 @@
        o.LeaveRunning = leaveRunning
 }
 
-// WithQueryName adds the name to the container restore libpod params
-func (o *ContainerRestoreLibpodParams) WithQueryName(name *string) 
*ContainerRestoreLibpodParams {
-       o.SetQueryName(name)
-       return o
-}
-
-// SetQueryName adds the name to the container restore libpod params
-func (o *ContainerRestoreLibpodParams) SetQueryName(name *string) {
-       o.QueryName = name
-}
-
 // WithPathName adds the name to the container restore libpod params
 func (o *ContainerRestoreLibpodParams) WithPathName(name string) 
*ContainerRestoreLibpodParams {
        o.SetPathName(name)
@@ -263,6 +252,17 @@
        o.PathName = name
 }
 
+// WithQueryName adds the name to the container restore libpod params
+func (o *ContainerRestoreLibpodParams) WithQueryName(name *string) 
*ContainerRestoreLibpodParams {
+       o.SetQueryName(name)
+       return o
+}
+
+// SetQueryName adds the name to the container restore libpod params
+func (o *ContainerRestoreLibpodParams) SetQueryName(name *string) {
+       o.QueryName = name
+}
+
 // WithPrintStats adds the printStats to the container restore libpod params
 func (o *ContainerRestoreLibpodParams) WithPrintStats(printStats *bool) 
*ContainerRestoreLibpodParams {
        o.SetPrintStats(printStats)
@@ -395,6 +395,11 @@
                }
        }
 
+       // path param name
+       if err := r.SetPathParam("name", o.PathName); err != nil {
+               return err
+       }
+
        if o.QueryName != nil {
 
                // query param name
@@ -412,11 +417,6 @@
                }
        }
 
-       // path param name
-       if err := r.SetPathParam("name", o.PathName); err != nil {
-               return err
-       }
-
        if o.PrintStats != nil {
 
                // query param printStats
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/client/generated/libpod/client/containers_compat/container_rename_parameters.go
 
new/client/generated/libpod/client/containers_compat/container_rename_parameters.go
--- 
old/client/generated/libpod/client/containers_compat/container_rename_parameters.go
 2024-11-04 21:06:53.817982497 +0100
+++ 
new/client/generated/libpod/client/containers_compat/container_rename_parameters.go
 2025-01-09 07:40:41.392551925 +0100
@@ -63,15 +63,15 @@
 
        /* Name.
 
-          New name for the container
+          Full or partial ID or full name of the container to rename
        */
-       QueryName string
+       PathName string
 
        /* Name.
 
-          Full or partial ID or full name of the container to rename
+          New name for the container
        */
-       PathName string
+       QueryName string
 
        timeout    time.Duration
        Context    context.Context
@@ -126,17 +126,6 @@
        o.HTTPClient = client
 }
 
-// WithQueryName adds the name to the container rename params
-func (o *ContainerRenameParams) WithQueryName(name string) 
*ContainerRenameParams {
-       o.SetQueryName(name)
-       return o
-}
-
-// SetQueryName adds the name to the container rename params
-func (o *ContainerRenameParams) SetQueryName(name string) {
-       o.QueryName = name
-}
-
 // WithPathName adds the name to the container rename params
 func (o *ContainerRenameParams) WithPathName(name string) 
*ContainerRenameParams {
        o.SetPathName(name)
@@ -148,6 +137,17 @@
        o.PathName = name
 }
 
+// WithQueryName adds the name to the container rename params
+func (o *ContainerRenameParams) WithQueryName(name string) 
*ContainerRenameParams {
+       o.SetQueryName(name)
+       return o
+}
+
+// SetQueryName adds the name to the container rename params
+func (o *ContainerRenameParams) SetQueryName(name string) {
+       o.QueryName = name
+}
+
 // WriteToRequest writes these params to a swagger request
 func (o *ContainerRenameParams) WriteToRequest(r runtime.ClientRequest, reg 
strfmt.Registry) error {
 
@@ -156,6 +156,11 @@
        }
        var res []error
 
+       // path param name
+       if err := r.SetPathParam("name", o.PathName); err != nil {
+               return err
+       }
+
        // query param name
        qrName := o.QueryName
        qName := qrName
@@ -166,11 +171,6 @@
                }
        }
 
-       // path param name
-       if err := r.SetPathParam("name", o.PathName); err != nil {
-               return err
-       }
-
        if len(res) > 0 {
                return errors.CompositeValidationError(res...)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/client/generated/libpod/models/swag_network_connect_request.go 
new/client/generated/libpod/models/swag_network_connect_request.go
--- old/client/generated/libpod/models/swag_network_connect_request.go  
2024-11-04 21:06:31.384967300 +0100
+++ new/client/generated/libpod/models/swag_network_connect_request.go  
2025-01-09 07:40:40.075882632 +0100
@@ -48,6 +48,10 @@
                res = append(res, err)
        }
 
+       if err := m.validateStaticMac(formats); err != nil {
+               res = append(res, err)
+       }
+
        if len(res) > 0 {
                return errors.CompositeValidationError(res...)
        }
@@ -75,6 +79,23 @@
        return nil
 }
 
+func (m *SwagNetworkConnectRequest) validateStaticMac(formats strfmt.Registry) 
error {
+       if swag.IsZero(m.StaticMac) { // not required
+               return nil
+       }
+
+       if err := m.StaticMac.Validate(formats); err != nil {
+               if ve, ok := err.(*errors.Validation); ok {
+                       return ve.ValidateName("static_mac")
+               } else if ce, ok := err.(*errors.CompositeError); ok {
+                       return ce.ValidateName("static_mac")
+               }
+               return err
+       }
+
+       return nil
+}
+
 // ContextValidate validate this swag network connect request based on the 
context it is used
 func (m *SwagNetworkConnectRequest) ContextValidate(ctx context.Context, 
formats strfmt.Registry) error {
        var res []error
@@ -83,6 +104,10 @@
                res = append(res, err)
        }
 
+       if err := m.contextValidateStaticMac(ctx, formats); err != nil {
+               res = append(res, err)
+       }
+
        if len(res) > 0 {
                return errors.CompositeValidationError(res...)
        }
@@ -105,6 +130,20 @@
        }
 
        return nil
+}
+
+func (m *SwagNetworkConnectRequest) contextValidateStaticMac(ctx 
context.Context, formats strfmt.Registry) error {
+
+       if err := m.StaticMac.ContextValidate(ctx, formats); err != nil {
+               if ve, ok := err.(*errors.Validation); ok {
+                       return ve.ValidateName("static_mac")
+               } else if ce, ok := err.(*errors.CompositeError); ok {
+                       return ce.ValidateName("static_mac")
+               }
+               return err
+       }
+
+       return nil
 }
 
 // MarshalBinary interface implementation

++++++ skupper-1.8.2.obscpio -> skupper-1.8.3.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/cmd/flow-collector/deploy.yaml 
new/skupper-1.8.3/cmd/flow-collector/deploy.yaml
--- old/skupper-1.8.2/cmd/flow-collector/deploy.yaml    2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/cmd/flow-collector/deploy.yaml    2025-01-08 
19:00:52.000000000 +0100
@@ -66,7 +66,7 @@
           #type: RuntimeDefault
       containers:
       - name: skupper-flow-collector
-        image: quay.io/skupper/flow-collector:1.8.2
+        image: quay.io/skupper/flow-collector:1.8.3
         imagePullPolicy: Always
         securityContext:
           capabilities:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/cmd/flow-collector/handlers.go 
new/skupper-1.8.3/cmd/flow-collector/handlers.go
--- old/skupper-1.8.2/cmd/flow-collector/handlers.go    2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/cmd/flow-collector/handlers.go    2025-01-08 
19:00:52.000000000 +0100
@@ -1,10 +1,14 @@
 package main
 
 import (
+       "bytes"
        "fmt"
        "io"
        "log"
        "net/http"
+       "os"
+       "path/filepath"
+       "regexp"
 
        "github.com/skupperproject/skupper/pkg/flow"
 )
@@ -226,3 +230,70 @@
                log.Printf("COLLECTOR: rangequery proxy response write error: 
%s", err.Error())
        }
 }
+
+func noAuth(h http.HandlerFunc) http.HandlerFunc {
+       return h
+}
+
+// basicAuthHandler handles basic auth for multiple users.
+type basicAuthHandler map[string]string
+
+func newBasicAuthHandler(root string) (basicAuthHandler, error) {
+       basicUsers := make(basicAuthHandler)
+
+       // Restrict usernames to files begining with an alphanumeric character
+       // Omits hidden files
+       fileRexp := regexp.MustCompile(`^[a-zA-Z0-9].*$`)
+
+       entries, err := os.ReadDir(root)
+       if err != nil {
+               return basicUsers, err
+       }
+       var buf bytes.Buffer
+       for _, entry := range entries {
+               if entry.IsDir() {
+                       continue
+               }
+               username := entry.Name()
+
+               if !fileRexp.MatchString(username) {
+                       continue
+               }
+               path := filepath.Join(root, username)
+               f, err := os.Open(path)
+               if err != nil {
+                       log.Printf("COLLECTOR: basic auth file open %q error: 
%s", path, err.Error())
+                       continue
+               }
+               defer f.Close()
+
+               buf.Reset()
+               if _, err := io.Copy(&buf, f); err != nil {
+                       log.Printf("COLLECTOR: basic auth file read %q error: 
%s", path, err.Error())
+                       continue
+               }
+
+               basicUsers[username] = buf.String()
+       }
+       return basicUsers, nil
+}
+
+func (h basicAuthHandler) HandlerFunc(next http.HandlerFunc) http.HandlerFunc {
+       return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+               user, password, ok := r.BasicAuth()
+
+               if ok && h.check(user, password) {
+                       next.ServeHTTP(w, r)
+                       return
+               }
+               w.Header().Set("WWW-Authenticate", "Basic realm=skupper")
+               http.Error(w, "Unauthorized", http.StatusUnauthorized)
+       })
+}
+
+func (h basicAuthHandler) check(user, given string) bool {
+       if required, ok := h[user]; ok {
+               return given == required
+       }
+       return false
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/cmd/flow-collector/handlers_test.go 
new/skupper-1.8.3/cmd/flow-collector/handlers_test.go
--- old/skupper-1.8.2/cmd/flow-collector/handlers_test.go       1970-01-01 
01:00:00.000000000 +0100
+++ new/skupper-1.8.3/cmd/flow-collector/handlers_test.go       2025-01-08 
19:00:52.000000000 +0100
@@ -0,0 +1,96 @@
+package main
+
+import (
+       "net/http"
+       "net/http/httptest"
+       "os"
+       "path/filepath"
+       "testing"
+)
+
+func TestBasic(t *testing.T) {
+       configuredUsers := map[string]string{
+               "test-user": "plaintext-password",
+               "admin":     "p@ssword!",
+       }
+       tmpDir := t.TempDir()
+       writeUser := func(usr, pwd string) {
+               userFile, err := os.Create(filepath.Join(tmpDir, usr))
+               if err != nil {
+                       t.Fatal(err)
+               }
+               defer userFile.Close()
+               userFile.Write([]byte(pwd))
+       }
+       for usr, pwd := range configuredUsers {
+               writeUser(usr, pwd)
+       }
+       writeUser("unreadable", "test") // ensure unreadable files are 
gracefully skipped
+       os.Chmod(filepath.Join(tmpDir, "unreadable"), 0220)
+
+       BasicAuth, err := newBasicAuthHandler(tmpDir)
+       if err != nil {
+               t.Fatal("unexpected error", err)
+       }
+
+       tstSrv := httptest.NewTLSServer(BasicAuth.HandlerFunc(func(rw 
http.ResponseWriter, r *http.Request) {
+               rw.Write([]byte("OK"))
+       }))
+       defer tstSrv.Close()
+       client := tstSrv.Client()
+       assertStatusCode := func(expected int, req *http.Request) {
+               t.Helper()
+               resp, err := client.Do(req)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               if resp.StatusCode != expected {
+                       t.Fatalf("expected http %d: got %d", expected, 
resp.StatusCode)
+               }
+       }
+       unauthenticated, _ := http.NewRequest(http.MethodGet, tstSrv.URL, nil)
+       assertStatusCode(401, unauthenticated)
+
+       incorrectPass, _ := http.NewRequest(http.MethodGet, tstSrv.URL, nil)
+       incorrectPass.SetBasicAuth("test-user", 
"X"+configuredUsers["test-user"])
+       assertStatusCode(401, incorrectPass)
+
+       incorrectUser, _ := http.NewRequest(http.MethodGet, tstSrv.URL, nil)
+       incorrectUser.SetBasicAuth("test-user-x", configuredUsers["test-user"])
+       assertStatusCode(401, incorrectPass)
+
+       unreadableUser, _ := http.NewRequest(http.MethodGet, tstSrv.URL, nil)
+       unreadableUser.SetBasicAuth("unreadable", "test")
+       assertStatusCode(401, unreadableUser)
+
+       mixedUserPass, _ := http.NewRequest(http.MethodGet, tstSrv.URL, nil)
+       mixedUserPass.SetBasicAuth("admin", configuredUsers["test-user"])
+       assertStatusCode(401, mixedUserPass)
+
+       for usr, pwd := range configuredUsers {
+               req, _ := http.NewRequest(http.MethodGet, tstSrv.URL, nil)
+               req.SetBasicAuth(usr, pwd)
+               assertStatusCode(200, req)
+       }
+}
+
+func FuzzBasic(f *testing.F) {
+       const (
+               tUser     = "skupper"
+               tPassword = "P@ssword!"
+       )
+       basic := basicAuthHandler{
+               tUser: tPassword,
+       }
+       f.Add(tUser, tPassword)
+       f.Add(tPassword, tUser)
+       f.Add(tUser, "")
+       f.Add("", tPassword)
+       f.Fuzz(func(t *testing.T, user, password string) {
+               expected := user == tUser && password == tPassword
+               out := basic.check(user, password)
+               if expected != out {
+                       t.Errorf("%q:%q does not match %q:%q", user, password, 
tUser, tPassword)
+               }
+       })
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/cmd/flow-collector/main.go 
new/skupper-1.8.3/cmd/flow-collector/main.go
--- old/skupper-1.8.2/cmd/flow-collector/main.go        2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/cmd/flow-collector/main.go        2025-01-08 
19:00:52.000000000 +0100
@@ -4,16 +4,13 @@
        "context"
        "encoding/base64"
        "encoding/json"
-       "errors"
        "flag"
        "fmt"
-       "io"
        "log"
        "net/http"
        _ "net/http/pprof"
        "os"
        "os/signal"
-       "path"
        "strconv"
        "syscall"
        "time"
@@ -55,8 +52,13 @@
        AuthMode string `json:"authType"`
 }
 
-var onlyOneSignalHandler = make(chan struct{})
-var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM}
+var (
+       // authenticated made variable to be swapped out at startup
+       authenticated func(next http.HandlerFunc) http.HandlerFunc = noAuth
+
+       onlyOneSignalHandler = make(chan struct{})
+       shutdownSignals      = []os.Signal{os.Interrupt, syscall.SIGTERM}
+)
 
 func getConnectInfo(file string) (connectJson, error) {
        cj := connectJson{}
@@ -102,46 +104,6 @@
        })
 }
 
-func authenticate(dir string, user string, password string) bool {
-       filename := path.Join(dir, user)
-       file, err := os.Open(filename)
-       if err != nil {
-               if errors.Is(err, os.ErrNotExist) {
-                       log.Printf("COLLECTOR: Failed to authenticate %s, no 
such user exists", user)
-               } else {
-                       log.Printf("COLLECTOR: Failed to authenticate %s: %s", 
user, err)
-               }
-               return false
-       }
-       defer file.Close()
-
-       bytes, err := io.ReadAll(file)
-       if err != nil {
-               log.Printf("COLLECTOR: Failed to authenticate %s: %s", user, 
err)
-               return false
-       }
-       return string(bytes) == password
-}
-
-func authenticated(h http.HandlerFunc) http.HandlerFunc {
-       dir := os.Getenv("FLOW_USERS")
-
-       if dir != "" {
-               return http.HandlerFunc(func(w http.ResponseWriter, r 
*http.Request) {
-                       user, password, ok := r.BasicAuth()
-
-                       if ok && authenticate(dir, user, password) {
-                               h.ServeHTTP(w, r)
-                       } else {
-                               w.Header().Set("WWW-Authenticate", "Basic 
realm=skupper")
-                               http.Error(w, "Unauthorized", 
http.StatusUnauthorized)
-                       }
-               })
-       } else {
-               return h
-       }
-}
-
 func getOpenshiftUser(r *http.Request) UserResponse {
        userResponse := UserResponse{
                Username: "",
@@ -208,6 +170,20 @@
        http.Error(w, "Unauthorized", http.StatusUnauthorized)
 }
 
+func configureAuth() error {
+       root := os.Getenv("FLOW_USERS")
+       if root == "" {
+               return nil
+       }
+       log.Printf("COLLECTOR: Configuring basic auth handler from %q \n", root)
+       basic, err := newBasicAuthHandler(root)
+       if err != nil {
+               return err
+       }
+       authenticated = basic.HandlerFunc
+       return nil
+}
+
 func main() {
        flags := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
        // if -version used, report and exit
@@ -219,7 +195,6 @@
                fmt.Println(version.Version)
                os.Exit(0)
        }
-
        // Startup message
        log.Printf("COLLECTOR: Starting Skupper Flow collector controller 
version %s \n", version.Version)
 
@@ -297,6 +272,10 @@
                }
        }
 
+       if err := configureAuth(); err != nil {
+               log.Fatalf("unrecoverable error setting up authentication: %s", 
err)
+       }
+
        tlsConfig := certs.GetTlsConfigRetriever(true, 
types.ControllerConfigPath+"tls.crt", types.ControllerConfigPath+"tls.key", 
types.ControllerConfigPath+"ca.crt")
 
        conn, err := getConnectInfo(types.ControllerConfigPath + "connect.json")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/cmd/site-controller/deploy-watch-all-ns.yaml 
new/skupper-1.8.3/cmd/site-controller/deploy-watch-all-ns.yaml
--- old/skupper-1.8.2/cmd/site-controller/deploy-watch-all-ns.yaml      
2024-11-04 12:08:20.000000000 +0100
+++ new/skupper-1.8.3/cmd/site-controller/deploy-watch-all-ns.yaml      
2025-01-08 19:00:52.000000000 +0100
@@ -194,7 +194,7 @@
           type: RuntimeDefault
       containers:
       - name: site-controller
-        image: quay.io/skupper/site-controller:1.8.2
+        image: quay.io/skupper/site-controller:1.8.3
         securityContext:
           capabilities:
             drop:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/cmd/site-controller/deploy-watch-current-ns.yaml 
new/skupper-1.8.3/cmd/site-controller/deploy-watch-current-ns.yaml
--- old/skupper-1.8.2/cmd/site-controller/deploy-watch-current-ns.yaml  
2024-11-04 12:08:20.000000000 +0100
+++ new/skupper-1.8.3/cmd/site-controller/deploy-watch-current-ns.yaml  
2025-01-08 19:00:52.000000000 +0100
@@ -137,7 +137,7 @@
           type: RuntimeDefault
       containers:
       - name: site-controller
-        image: quay.io/skupper/site-controller:1.8.2
+        image: quay.io/skupper/site-controller:1.8.3
         securityContext:
           capabilities:
             drop:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/pkg/domain/podman/service.go 
new/skupper-1.8.3/pkg/domain/podman/service.go
--- old/skupper-1.8.2/pkg/domain/podman/service.go      2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/pkg/domain/podman/service.go      2025-01-08 
19:00:52.000000000 +0100
@@ -195,7 +195,7 @@
        var svcRouterConfig *qdr.RouterConfig
        var svcRouterConfigStr string
        var configVolume *container.Volume
-       svcRouterConfig, svcRouterConfigStr, err = 
domain.CreateRouterServiceConfig(site, routerConfig, servicePodman)
+       svcRouterConfig, svcRouterConfigStr, err = 
domain.CreateRouterServiceConfig(site, routerConfig, servicePodman, 
servicePodman.GetContainerName())
 
        // Creating directory inside skupper-internal volume to store config 
for service router
        configFile := path.Join(servicePodman.Address, 
types.TransportConfigFile)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/pkg/domain/podman/service_test.go 
new/skupper-1.8.3/pkg/domain/podman/service_test.go
--- old/skupper-1.8.2/pkg/domain/podman/service_test.go 2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/pkg/domain/podman/service_test.go 2025-01-08 
19:00:52.000000000 +0100
@@ -4,11 +4,14 @@
 package podman
 
 import (
+       "fmt"
+       "strconv"
        "testing"
 
        "github.com/skupperproject/skupper/api/types"
        "github.com/skupperproject/skupper/client/container"
        "github.com/skupperproject/skupper/pkg/domain"
+       "github.com/skupperproject/skupper/pkg/qdr"
        "gotest.tools/assert"
 )
 
@@ -161,3 +164,191 @@
                }
        })
 }
+
+func TestCreateRouterServiceConfig(t *testing.T) {
+
+       fakeService := func(address string, ports []int, containerName string) 
*Service {
+               svc := &Service{
+                       ServiceCommon: &domain.ServiceCommon{
+                               Address:  address,
+                               Ports:    ports,
+                               Protocol: "tcp",
+                       },
+                       ContainerName: containerName,
+               }
+               return svc
+       }
+       site := &Site{
+               SiteCommon: &domain.SiteCommon{
+                       Name: "my-site-name",
+                       Id:   "my-site-id",
+               },
+       }
+       parentConfig := &qdr.RouterConfig{
+               LogConfig: map[string]qdr.LogConfig{
+                       "DEFAULT": qdr.LogConfig{
+                               Module: "DEFAULT",
+                               Enable: "info+",
+                       },
+               },
+       }
+       egressResolvers := func(service *Service) {
+               service.AddEgressResolver(&domain.EgressResolverHost{
+                       Host:  "10.0.0.1",
+                       Ports: map[int]int{8080: 8080},
+               })
+               service.AddEgressResolver(&domain.EgressResolverHost{
+                       Host:  "10.0.0.2",
+                       Ports: map[int]int{8080: 8081},
+               })
+       }
+       scenarios := []struct {
+               name     string
+               service  *Service
+               modifier func(*Service)
+               expError bool
+       }{
+               {
+                       name:    "basic-service-tcp",
+                       service: fakeService("address", []int{8080}, ""),
+               },
+               {
+                       name:    "basic-service-tcp-custom-container",
+                       service: fakeService("address", []int{8080}, 
"custom-address"),
+               },
+               {
+                       name:    "basic-service-tcp-multiple-ports",
+                       service: fakeService("address", []int{8080, 8081, 
8082}, ""),
+               },
+               {
+                       name:    "basic-service-http",
+                       service: fakeService("address", []int{8080}, ""),
+                       modifier: func(service *Service) {
+                               service.Protocol = "http"
+                       },
+               },
+               {
+                       name:    "basic-service-http2",
+                       service: fakeService("address", []int{8080}, ""),
+                       modifier: func(service *Service) {
+                               service.Protocol = "http2"
+                       },
+               },
+               {
+                       name:    "basic-service-tls",
+                       service: fakeService("address", []int{8080}, ""),
+                       modifier: func(service *Service) {
+                               service.TlsCredentials = "my-credentials"
+                       },
+               },
+               {
+                       name:     "basic-service-tcp-with-targets",
+                       service:  fakeService("address", []int{8080}, ""),
+                       modifier: egressResolvers,
+               },
+               {
+                       name:    "basic-service-http-with-targets",
+                       service: fakeService("address", []int{8080}, ""),
+                       modifier: func(service *Service) {
+                               service.Protocol = "http"
+                               egressResolvers(service)
+                       },
+               },
+               {
+                       name:    "basic-service-http2-with-targets",
+                       service: fakeService("address", []int{8080}, ""),
+                       modifier: func(service *Service) {
+                               service.Protocol = "http2"
+                               egressResolvers(service)
+                       },
+               },
+       }
+       for _, scenario := range scenarios {
+               t.Run(scenario.name, func(t *testing.T) {
+                       if scenario.modifier != nil {
+                               scenario.modifier(scenario.service)
+                       }
+                       routerConfig, routerConfigStr, err := 
domain.CreateRouterServiceConfig(site, parentConfig, scenario.service, 
scenario.service.GetContainerName())
+                       if scenario.expError {
+                               assert.Assert(t, err != nil)
+                               return
+                       }
+                       assert.Assert(t, err == nil)
+                       assert.Assert(t, routerConfig != nil)
+                       assert.Assert(t, routerConfigStr != "")
+
+                       var expectedTcpListeners int
+                       var expectedHttpListeners int
+                       var expectedPorts = len(scenario.service.Ports)
+                       switch scenario.service.Protocol {
+                       case "tcp":
+                               expectedTcpListeners = expectedPorts
+                       case "http":
+                               expectedHttpListeners = expectedPorts
+                       case "http2":
+                               expectedHttpListeners = expectedPorts
+                       }
+                       assert.Equal(t, len(routerConfig.Bridges.TcpListeners), 
expectedTcpListeners)
+                       assert.Equal(t, 
len(routerConfig.Bridges.HttpListeners), expectedHttpListeners)
+
+                       var sslProfilesExpected = 1
+                       if scenario.service.IsTls() {
+                               sslProfilesExpected++
+                       }
+                       assert.Equal(t, sslProfilesExpected, 
len(routerConfig.SslProfiles))
+
+                       for _, port := range scenario.service.Ports {
+                               addressIndex := fmt.Sprintf("%s:%d", 
scenario.service.Address, port)
+                               if expectedTcpListeners > 0 {
+                                       tcpListener := 
routerConfig.Bridges.TcpListeners[addressIndex]
+                                       if scenario.service.ContainerName == "" 
{
+                                               assert.Equal(t, 
tcpListener.Host, scenario.service.Address)
+                                       } else {
+                                               assert.Equal(t, 
tcpListener.Host, scenario.service.ContainerName)
+                                       }
+                                       assert.Equal(t, tcpListener.Address, 
addressIndex)
+                                       assert.Equal(t, tcpListener.Port, 
strconv.Itoa(port))
+
+                                       assert.Equal(t, 
len(scenario.service.GetEgressResolvers()), 
len(routerConfig.Bridges.TcpConnectors))
+                                       for _, egressResolver := range 
scenario.service.GetEgressResolvers() {
+                                               egresses, err := 
egressResolver.Resolve()
+                                               assert.Assert(t, err)
+                                               for _, egress := range egresses 
{
+                                                       targetHost := 
egress.GetHost()
+                                                       for _, targetPort := 
range egress.GetPorts() {
+                                                               connectorName 
:= fmt.Sprintf("%s@%s:%d:%d", scenario.service.Address, targetHost, port, 
targetPort)
+                                                               connector, ok 
:= routerConfig.Bridges.TcpConnectors[connectorName]
+                                                               
assert.Assert(t, ok)
+                                                               assert.Equal(t, 
strconv.Itoa(targetPort), connector.Port)
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       httpListener := 
routerConfig.Bridges.HttpListeners[addressIndex]
+                                       if scenario.service.ContainerName == "" 
{
+                                               assert.Equal(t, 
httpListener.Host, scenario.service.Address)
+                                       } else {
+                                               assert.Equal(t, 
httpListener.Host, scenario.service.ContainerName)
+                                       }
+                                       assert.Equal(t, httpListener.Address, 
addressIndex)
+                                       assert.Equal(t, httpListener.Port, 
strconv.Itoa(port))
+
+                                       assert.Equal(t, 
len(scenario.service.GetEgressResolvers()), 
len(routerConfig.Bridges.HttpConnectors))
+                                       for _, egressResolver := range 
scenario.service.GetEgressResolvers() {
+                                               egresses, err := 
egressResolver.Resolve()
+                                               assert.Assert(t, err)
+                                               for _, egress := range egresses 
{
+                                                       targetHost := 
egress.GetHost()
+                                                       for _, targetPort := 
range egress.GetPorts() {
+                                                               connectorName 
:= fmt.Sprintf("%s@%s:%d:%d", scenario.service.Address, targetHost, port, 
targetPort)
+                                                               connector, ok 
:= routerConfig.Bridges.HttpConnectors[connectorName]
+                                                               
assert.Assert(t, ok)
+                                                               assert.Equal(t, 
strconv.Itoa(targetPort), connector.Port)
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               })
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/pkg/domain/podman/site_test.go 
new/skupper-1.8.3/pkg/domain/podman/site_test.go
--- old/skupper-1.8.2/pkg/domain/podman/site_test.go    2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/pkg/domain/podman/site_test.go    2025-01-08 
19:00:52.000000000 +0100
@@ -460,7 +460,7 @@
                }, {
                        ID:     strings.Replace(uuid.New().String(), "-", "", 
-1),
                        Name:   "nginx",
-                       Image:  
"docker.io/nginxinc/nginx-unprivileged:stable-alpine",
+                       Image:  
"quay.io/skupper/nginx-unprivileged:stable-alpine",
                        Labels: map[string]string{},
                        Networks: map[string]container.ContainerNetworkInfo{
                                "skupper": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/pkg/domain/service.go 
new/skupper-1.8.3/pkg/domain/service.go
--- old/skupper-1.8.2/pkg/domain/service.go     2024-11-04 12:08:20.000000000 
+0100
+++ new/skupper-1.8.3/pkg/domain/service.go     2025-01-08 19:00:52.000000000 
+0100
@@ -199,7 +199,7 @@
        }
 }
 
-func CreateRouterServiceConfig(site Site, parentRouterConfig 
*qdr.RouterConfig, service Service) (*qdr.RouterConfig, string, error) {
+func CreateRouterServiceConfig(site Site, parentRouterConfig 
*qdr.RouterConfig, service Service, serviceHostname string) (*qdr.RouterConfig, 
string, error) {
 
        // Create router config
        siteName := fmt.Sprintf("%s-%s", site.GetName(), service.GetAddress())
@@ -241,6 +241,7 @@
                case "tcp":
                        svcRouterConfig.AddTcpListener(qdr.TcpEndpoint{
                                Name:       listenerName,
+                               Host:       serviceHostname,
                                Port:       listenerPort,
                                Address:    listenerAddr,
                                SiteId:     siteId,
@@ -249,6 +250,7 @@
                case "http":
                        svcRouterConfig.AddHttpListener(qdr.HttpEndpoint{
                                Name:         listenerName,
+                               Host:         serviceHostname,
                                Port:         listenerPort,
                                Address:      listenerAddr,
                                SiteId:       siteId,
@@ -258,6 +260,7 @@
                case "http2":
                        svcRouterConfig.AddHttpListener(qdr.HttpEndpoint{
                                Name:            listenerName,
+                               Host:            serviceHostname,
                                Port:            listenerPort,
                                Address:         listenerAddr,
                                SiteId:          siteId,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/pkg/flow/flow_mem_driver.go 
new/skupper-1.8.3/pkg/flow/flow_mem_driver.go
--- old/skupper-1.8.2/pkg/flow/flow_mem_driver.go       2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/pkg/flow/flow_mem_driver.go       2025-01-08 
19:00:52.000000000 +0100
@@ -2804,7 +2804,6 @@
        diff := uint64(time.Now().UnixNano())/uint64(time.Microsecond) - 
diffTime
        found := false
        if diff > wait && flow.Process == nil {
-               log.Printf("COLLECTOR: Associating flow %s to external process 
%s\n", flow.Identity, processName)
                for _, process := range fc.Processes {
                        if process.Name != nil && *process.Name == processName {
                                flow.Process = &process.Identity
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/pkg/images/images.go 
new/skupper-1.8.3/pkg/images/images.go
--- old/skupper-1.8.2/pkg/images/images.go      2024-11-04 12:08:20.000000000 
+0100
+++ new/skupper-1.8.3/pkg/images/images.go      2025-01-08 19:00:52.000000000 
+0100
@@ -2,12 +2,12 @@
 
 const (
        DefaultImageRegistry       string = "quay.io/skupper"
-       RouterImageName            string = "skupper-router:2.7.2"
-       ServiceControllerImageName string = "service-controller:1.8.2"
-       ControllerPodmanImageName  string = "controller-podman:1.8.2"
-       ConfigSyncImageName        string = "config-sync:1.8.2"
-       FlowCollectorImageName     string = "flow-collector:1.8.2"
-       SiteControllerImageName    string = "site-controller:1.8.2"
+       RouterImageName            string = "skupper-router:2.7.3"
+       ServiceControllerImageName string = "service-controller:1.8.3"
+       ControllerPodmanImageName  string = "controller-podman:1.8.3"
+       ConfigSyncImageName        string = "config-sync:1.8.3"
+       FlowCollectorImageName     string = "flow-collector:1.8.3"
+       SiteControllerImageName    string = "site-controller:1.8.3"
        PrometheusImageRegistry    string = "quay.io/prometheus"
        PrometheusServerImageName  string = "prometheus:v2.42.0"
        OauthProxyImageRegistry    string = "quay.io/openshift"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/Containerfile.hey 
new/skupper-1.8.3/test/images/Containerfile.hey
--- old/skupper-1.8.2/test/images/Containerfile.hey     1970-01-01 
01:00:00.000000000 +0100
+++ new/skupper-1.8.3/test/images/Containerfile.hey     2025-01-08 
19:00:52.000000000 +0100
@@ -0,0 +1,26 @@
+ARG TARGETPLATFORM
+
+FROM --platform=$TARGETPLATFORM golang:1.21 AS builder
+
+ARG TARGETOS
+ARG TARGETARCH
+
+WORKDIR /go/src/app
+RUN git clone https://github.com/rakyll/hey.git ./
+RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o hey ./hey.go
+
+FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9-minimal
+
+# The image needs to be compatible with the older entry point used
+# in the previous version
+RUN ln -s /app/hey /usr/bin/hey_linux_amd64
+
+# Create user and group and switch to user's context
+RUN microdnf -y install shadow-utils \
+&& microdnf clean all
+RUN useradd --uid 10000 runner
+USER 10000
+
+WORKDIR /app
+COPY --from=builder /go/src/app/hey .
+CMD ["/app/hey"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/Containerfile.iperf3 
new/skupper-1.8.3/test/images/Containerfile.iperf3
--- old/skupper-1.8.2/test/images/Containerfile.iperf3  1970-01-01 
01:00:00.000000000 +0100
+++ new/skupper-1.8.3/test/images/Containerfile.iperf3  2025-01-08 
19:00:52.000000000 +0100
@@ -0,0 +1,18 @@
+ARG TARGETPLATFORM
+
+FROM --platform=$TARGETPLATFORM quay.io/fedora/fedora-minimal
+
+LABEL description="A supporting test image"
+LABEL maintainer="Skupper project"
+LABEL origin=https://github.com/skupperproject/skupper/blob/main/test/images
+
+EXPOSE 5201
+
+# Create user and group and switch to user's context
+RUN microdnf -y install iperf3 shadow-utils \
+&& microdnf clean all
+RUN useradd --uid 10000 runner
+USER 10000
+
+CMD []
+ENTRYPOINT ["/usr/bin/iperf3"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/Containerfile.nghttp2 
new/skupper-1.8.3/test/images/Containerfile.nghttp2
--- old/skupper-1.8.2/test/images/Containerfile.nghttp2 1970-01-01 
01:00:00.000000000 +0100
+++ new/skupper-1.8.3/test/images/Containerfile.nghttp2 2025-01-08 
19:00:52.000000000 +0100
@@ -0,0 +1,11 @@
+ARG TARGETPLATFORM
+
+FROM --platform=$TARGETPLATFORM alpine:latest
+
+LABEL description="A supporting test image containing nghttp2 (client, server 
and load tester), for Skupper testing.  By default, this image does not start 
any nghttp2 project; the user needs to overwrite CMD with the command they want"
+LABEL maintainer="Skupper project"
+LABEL origin=https://github.com/skupperproject/skupper/blob/main/test/images
+
+RUN apk add --no-cache nghttp2
+
+CMD ["ls"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/Containerfile.wrk 
new/skupper-1.8.3/test/images/Containerfile.wrk
--- old/skupper-1.8.2/test/images/Containerfile.wrk     1970-01-01 
01:00:00.000000000 +0100
+++ new/skupper-1.8.3/test/images/Containerfile.wrk     2025-01-08 
19:00:52.000000000 +0100
@@ -0,0 +1,17 @@
+ARG TARGETPLATFORM
+
+FROM --platform=$TARGETPLATFORM registry.fedoraproject.org/fedora-minimal AS 
build
+
+RUN microdnf -y install gcc git make unzip openssl-devel && microdnf -y clean 
all
+
+WORKDIR /home/root
+RUN git clone https://github.com/wg/wrk.git
+
+WORKDIR /home/root/wrk
+RUN make WITH_OPENSSL=/usr
+
+FROM registry.fedoraproject.org/fedora-minimal
+
+COPY --from=build /home/root/wrk/wrk /usr/bin/wrk
+
+CMD ["/usr/bin/wrk"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/Containerfile.wrk2 
new/skupper-1.8.3/test/images/Containerfile.wrk2
--- old/skupper-1.8.2/test/images/Containerfile.wrk2    1970-01-01 
01:00:00.000000000 +0100
+++ new/skupper-1.8.3/test/images/Containerfile.wrk2    2025-01-08 
19:00:52.000000000 +0100
@@ -0,0 +1,13 @@
+ARG TARGETPLATFORM
+
+FROM --platform=$TARGETPLATFORM alpine:latest as builder
+
+RUN apk add --update alpine-sdk openssl-dev zlib-dev && apk add --no-cache git 
&& git clone https://github.com/giltene/wrk2.git && cd wrk2 && make && mv wrk 
/bin/
+
+
+FROM alpine:latest
+
+RUN apk add --update libgcc openssl zlib
+COPY --from=builder /bin/wrk /bin/
+
+CMD ["/bin/sh"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/Dockerfile.nghttp2 
new/skupper-1.8.3/test/images/Dockerfile.nghttp2
--- old/skupper-1.8.2/test/images/Dockerfile.nghttp2    2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/images/Dockerfile.nghttp2    1970-01-01 
01:00:00.000000000 +0100
@@ -1,9 +0,0 @@
-FROM alpine:latest
-
-LABEL description="A supporting test image containing nghttp2 (client, server 
and load tester), for Skupper testing.  By default, this image does not start 
any nghttp2 project; the user needs to overwrite CMD with the command they want"
-LABEL maintainer="Skupper project"
-LABEL origin=https://github.com/skupperproject/skupper/blob/main/test/images
-
-RUN apk add --no-cache nghttp2
-
-CMD ["ls"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/Makefile 
new/skupper-1.8.3/test/images/Makefile
--- old/skupper-1.8.2/test/images/Makefile      2024-11-04 12:08:20.000000000 
+0100
+++ new/skupper-1.8.3/test/images/Makefile      2025-01-08 19:00:52.000000000 
+0100
@@ -1,30 +1,35 @@
 # This make file provides three operations:
 #
-# - Copy a list of images (hardcoded below) to a main repository (by default,
-#   quay.io/skupper)
-# - Generate and push images to that same repository, based on Dockerfiles
-# - Copy both lists of images above (external and generated) to another,
-#   configurable repository
+# - Copy (replicate) a list of images (hardcoded below) to a main repository
+#   (by default, quay.io/skupper), possibly modifying and reassembling them
+# - Generate and push images to that same repository, based on Containerfiles
+#   located on this directory
+# - Copy both lists of images above (replicated and generated) to another,
+#   configurable repository, along with other two lists, which are generally
+#   used from their original locations ('other' and 'external').
 #
 # See the README.md for the rationale of each of them.
 #
-# The basic operation is to copy or generate-and-push a single image into
+# The basic operation is to replicate or generate-and-push a single image into
 # the MAIN_REPO:
 #
 #   make docker.io/svagi/nghttp2
+#   make docker.io/nginxinc/nginx-unprivileged
 #   make nghttp2
 #
-# The possible values are those listed on EXTERNAL_IMAGES and GENERATED_IMAGES.
+# The possible values are those listed on REPLICATED_IMAGES, REASSEMBLED_IMAGES
+# and GENERATED_IMAGES.
 #
 # You can also only build an image (and not push it).  Just add _build to the
 # image name listed in GENERATED_IMAGES:
 #
 #   make nghttp2_build
 #
-# Alternativelly, one can build/push or copy all generated, all external, or
-# all of them:
+# Alternativelly, one can build/push or copy all generated, all replicated, all
+# reassembled, or all of them:
 #
-#   make external_images
+#   make replicated_images
+#   make reassembled_images
 #   make generated_images
 #   make everything
 #
@@ -35,9 +40,9 @@
 # As with any Makefile, you can configure the execution by setting variables
 # on the make invocation:
 #
-#   make MAIN_REPO=quay.io/dhashimo docker.io/ssorj/quiver
+#   make MAIN_REPO=quay.io/dhashimo docker.io/library/redis:alpine
 #
-# The command above will copy docker.io/ssorj/quiver into the quay repository
+# The command above will copy docker.io/library/redis:alpine into the quay 
repository
 # quay.io/dhashimo, instead of the default MAIN_REPO
 #
 #   make MAIN_REPO=quay.io/dhashimo everything
@@ -50,15 +55,16 @@
 #
 #   make COPY_REPO=192.168.0.1:5000/internal copy
 #
-# The command above will copy all images (external and generated, as listed
-# below) from the MAIN_REPO into the 'internal' repository within the
-# registry running at 192.168.0.1:5000.
+# The command above will copy all images (replicated, generated, reassembled,
+# external and other, as listed below) from the MAIN_REPO into the 'internal'
+# repository within the registry running at 192.168.0.1:5000.
 #
 # Individual items can also be specified.  For that, just add '_copy' to
 # their main target names:
 #
 #   make COPY_REPO=192.168.0.1:5000/internal nghttp2_copy
-#   make COPY_REPO=192.168.0.1:5000/internal docker.io/ssorj/quiver_copy
+#   make COPY_REPO=192.168.0.1:5000/internal 
docker.io/library/redis:alpine_copy
+#   make COPY_REPO=192.168.0.1:5000/internal 
docker.io/nginxinc/nginx-unprivileged_copy
 #
 # This Makefile is intended to be executed manually, with the login of
 # individual users, and not by a robot account on a CI.
@@ -80,32 +86,89 @@
 # That is required for their use with Openshift 3.11
 FORMAT_OPTIONS = --format docker
 TRANSFORM_OPTIONS = --format v2s2
+PLATFORM = linux/amd64,linux/arm64
 
 # Repositories
 MAIN_REPO = quay.io/skupper
 COPY_REPO = localhost:5000/local
 
-# This is the list of external images that will be copied to $(MAIN_REPO).  If
+# Set this to copy a specific tag from quay.io/skupper/skupper-tests on
+# the copy operation.  If you do so, include the colon - ":1.5"
+SKUPPER_TESTS_IMAGE_VERSION =
+
+# This is the list of replicated images that will be copied to $(MAIN_REPO).  
If
 # the image specifies a tag, make sure to escape the colon with a backslash
 # (such as in docker.io/library/mongo\:5.0).  Otherwise, you'll get an error
 # like `multiple target patterns.  Stop.`
-EXTERNAL_IMAGES := \
-       docker.io/nginxinc/nginx-unprivileged \
-       docker.io/ssorj/quiver \
+REPLICATED_IMAGES := \
+       docker.io/library/postgres\:9.5 \
+
+
+# These manifest lists require special handling; they contain 'images' with
+# os/arch/variant "unknown" and the following entry in LayersData.Annotations:
+#
+#    in-toto.io/predicate-type": "https://slsa.dev/provenance/v0.2
+#
+# That makes a plain skopeo copy --all --format v2s2 to fail with an error
+# like the one below:
+#
+#    copying image 8/14 from manifest list: creating an updated image 
manifest: Unknown media type during manifest conversion: 
"application/vnd.in-toto+json"
+#
+# (see https://github.com/containers/skopeo/issues/1874)
+#
+# For that reason, we need to first copy the image locally, change its
+# manifest, and only then copy it to its destination.
+REASSEMBLED_IMAGES := \
+       docker.io/library/mongo\:5.0 \
        docker.io/library/postgres \
        docker.io/library/redis \
-       docker.io/maistra/examples-bookinfo-productpage-v1\:0.12.0 \
-       docker.io/maistra/examples-bookinfo-ratings-v1\:0.12.0 \
-       docker.io/maistra/examples-bookinfo-details-v1\:0.12.0 \
-       docker.io/maistra/examples-bookinfo-reviews-v3\:0.12.0 \
-       docker.io/library/mongo\:5.0 \
-       docker.io/nginxinc/nginx-unprivileged\:stable-alpine
+       docker.io/nginxinc/nginx-unprivileged \
+       docker.io/nginxinc/nginx-unprivileged\:stable-alpine \
+       docker.io/library/redis\:alpine \
+       docker.io/istio/examples-bookinfo-productpage-v1\:1.19.1 \
+       docker.io/istio/examples-bookinfo-ratings-v1\:1.19.1 \
+       docker.io/istio/examples-bookinfo-details-v1\:1.19.1 \
+       docker.io/istio/examples-bookinfo-reviews-v3\:1.19.1
 
 # These are the images that are generated by this Makefile (as opposed to
 # created elsewhere and just copied here).  To add a new image, simply create
-# Dockerfile.IMAGENAME and add the IMAGENAME below.
+# Containerfile.IMAGENAME and add the IMAGENAME below.
 GENERATED_IMAGES := \
-       nghttp2
+       hey \
+       iperf3 \
+       nghttp2 \
+       wrk
+
+# wrk2 does not support ARM: https://github.com/giltene/wrk2/issues/104
+
+# These are generated by other repositories under 
https://github.com/skupperproject/,
+# and placed directly on quay.  We list them here, so they can be part of the 
list of images
+# to be copied to a private repo
+OTHER_IMAGES := \
+       quay.io/skupper/wrk2 \
+       quay.io/skupper/tcp-go-echo \
+       quay.io/skupper/hello-world-frontend \
+       quay.io/skupper/hello-world-backend \
+       quay.io/skupper/skupper-tests${SKUPPER_TESTS_IMAGE_VERSION}
+
+# These images are external to the project, and they are not copied into our 
quay;
+# the tests access them with their original names, and we do not do any special
+# handling on them.  They are listed here just so they can be used on the copy
+# operation.
+EXTERNAL_IMAGES := \
+       quay.io/ssorj/quiver \
+       gcr.io/google-samples/microservices-demo/adservice\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/cartservice\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/checkoutservice\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/currencyservice\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/emailservice\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/frontend\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/loadgenerator\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/paymentservice\:v0.10.1 \
+       gcr.io/google-samples/microservices-demo/productcatalogservice\:v0.10.1 
\
+       gcr.io/google-samples/microservices-demo/recommendationservice\:v0.10.1 
\
+       gcr.io/google-samples/microservices-demo/shippingservice\:v0.10.1 \
+       registry.access.redhat.com/rhscl/postgresql-95-rhel7
 
 # --- end of configuration ---
 
@@ -116,7 +179,10 @@
 
 # The copy target names, to be used with the copy operation
 generated_copy := $(patsubst %,%_copy,$(GENERATED_IMAGES))
-external_copy   := $(patsubst %,%_copy,$(EXTERNAL_IMAGES))
+replicated_copy   := $(patsubst %,%_copy,$(REPLICATED_IMAGES))
+reassembled_copy := $(patsubst %,%_copy,$(REASSEMBLED_IMAGES))
+external_copy := $(patsubst %,%_copy,$(EXTERNAL_IMAGES))
+other_copy := $(patsubst %,%_copy,$(OTHER_IMAGES))
 
 # We don't want someone to just run `make` and start copying stuff
 # around, so instead the default operation is to just give some
@@ -129,52 +195,118 @@
        @echo Normal use, however, is to select individual targets.
        @echo Check Makefile contents for documentation.
 
-# For a generated image, we simply have a Dockerfile named after it and call
+# For a generated image, we simply have a Containerfile named after it and call
 # `podman build` on it, tagging it on the MAIN_REPO
+# TODO: list Containerfiles as pre-reqs?
 $(generated_build): TARGET = $(patsubst %_build,%,$@)
 $(generated_build):
-       $(PODMAN) build $(FORMAT_OPTIONS) --file Dockerfile.$(TARGET) --tag 
$(MAIN_REPO)/$(TARGET)
+       # Generate $(TARGET)
+# First, we need to remove any existing manifest, as the command below is 
additive
+# (it would append builds to an existing manifest)
+       -$(PODMAN) manifest rm $(MAIN_REPO)/$(TARGET)
+       $(PODMAN) build --platform $(PLATFORM) --no-cache $(FORMAT_OPTIONS) 
--file Containerfile.$(TARGET) --manifest $(MAIN_REPO)/$(TARGET)
 
-# This is generic the push target, for images built here (GENERATED_IMAGES)
+# This is the generic push target, for images built here (GENERATED_IMAGES)
 # Each image depends on its respective _build target
 %: %_build
-       $(PODMAN) push $(MAIN_REPO)/$@
+       $(PODMAN) manifest push $(MAIN_REPO)/$@
 
 # Shortcut targets
-external_images: $(EXTERNAL_IMAGES)
+replicated_images: $(REPLICATED_IMAGES)
+reassembled_images: $(REASSEMBLED_IMAGES)
 generated_images: $(GENERATED_IMAGES)
-everything: external_images generated_images
+# note OTHER_IMAGES and EXTERNAL_IMAGES are not part of 'everything', as these
+# are already in the places where the tests get them from; they're used only
+# on the copy operation
+everything: replicated_images generated_images reassembled_images
 
-# This is the main target for the external images; it copies them from their
+# This is the main target for the replicated images; it copies them from their
 # original locations _into_ MAIN_REPO.  Do not confuse this for the `copy` 
operation
 # below, that copies _from_ MAIN_REPO into COPY_REPO.
 #
 # The first line prepares a target-local TARGET variable, which contains only
+# the last part of the URL (the image name proper + tag)
+$(REPLICATED_IMAGES): TARGET = $(shell echo "$@" | sed s_.*/__ )
+$(REPLICATED_IMAGES):
+       # Copy $(TARGET) from the replicated list
+       $(SKOPEO) copy --all $(TRANSFORM_OPTIONS) \
+               docker://$@ \
+               docker://$(MAIN_REPO)/$(TARGET)
+
+# This is the main target for the reassembled images; it copies them from their
+# original locations to a temporary directory, modifies the manifest.json and 
then
+# copies them _into_ MAIN_REPO.
+#
+# The first line prepares a target-local TARGET variable, which contains only
 # the last part of the URL
-$(EXTERNAL_IMAGES): TARGET = $(shell echo "$@" | sed s_.*/__ )
-$(EXTERNAL_IMAGES):
-       $(SKOPEO) copy $(TRANSFORM_OPTIONS) \
+$(REASSEMBLED_IMAGES): TARGET = $(shell echo "$@" | sed s_.*/__ )
+$(REASSEMBLED_IMAGES): REASSEMBLE_TMPDIR ::= /tmp/$(shell mktemp -d 
image-reassembly-XXX )
+$(REASSEMBLED_IMAGES):
+       # Reassemble $(TARGET)
+       $(SKOPEO) copy --all \
                docker://$@ \
+               dir://$(REASSEMBLE_TMPDIR)
+
+       ls $(REASSEMBLE_TMPDIR)
+
+       jq \
+               '(.manifests[] | select (.platform.os == "unknown")) |= del (.) 
| del (..|nulls)' \
+               $(REASSEMBLE_TMPDIR)/manifest.json > 
$(REASSEMBLE_TMPDIR)/manifest.json.new
+
+       mv $(REASSEMBLE_TMPDIR)/manifest.json.new 
$(REASSEMBLE_TMPDIR)/manifest.json
+
+       $(SKOPEO) copy --all $(TRANSFORM_OPTIONS) \
+               dir://$(REASSEMBLE_TMPDIR) \
                docker://$(MAIN_REPO)/$(TARGET)
 
+       rm -rf $(REASSEMBLE_TMPDIR)
+
 #
 # Copy operation
 #
-copy: $(generated_copy) $(external_copy)
+copy: $(generated_copy) $(replicated_copy) $(reassembled_copy) 
$(external_copy) $(other_copy)
 
-# The targets for external and generated images are basically the same; the
+# The targets for replicated and generated images are basically the same; the
 # only difference is the way the original/main target needs to be manipulated
 # to generate the image name+tag (saved in the target-local variable TARGET).
 
 $(generated_copy): TARGET = $(patsubst %_copy,%,$@)
 $(generated_copy):
-       $(SKOPEO) copy $(TRANSFORM_OPTIONS) \
+       # copy $(TARGET) from generated list
+       $(SKOPEO) copy --all $(TRANSFORM_OPTIONS) \
                docker://$(MAIN_REPO)/$(TARGET) \
                docker://$(COPY_REPO)/$(TARGET)
 
-# Remove _copy, but also everything till the last /
-$(external_copy): TARGET = $(shell echo "$@" | sed -e "s/_copy$$//" -e 
's_.*/__' )
-$(external_copy):
-       $(SKOPEO) copy $(TRANSFORM_OPTIONS) \
+# Remove _copy, but also everything till the last "/" (registry and prefix),
+# as we'll use MAIN_REPO and COPY_REPO, instead.
+$(replicated_copy): TARGET = $(shell echo "$@" | sed -e "s/_copy$$//" -e 
's_.*/__' )
+$(replicated_copy):
+       # copy $(TARGET) from the replicated list
+       $(SKOPEO) copy --all $(TRANSFORM_OPTIONS) \
                docker://$(MAIN_REPO)/$(TARGET) \
                docker://$(COPY_REPO)/$(TARGET)
+
+$(reassembled_copy): TARGET = $(shell echo "$@" | sed -e "s/_copy$$//" -e 
's_.*/__' )
+$(reassembled_copy):
+       # copy $(TARGET) from the reassembled list
+       $(SKOPEO) copy --all $(TRANSFORM_OPTIONS) \
+               docker://$(MAIN_REPO)/$(TARGET) \
+               docker://$(COPY_REPO)/$(TARGET)
+
+# OTHER_IMAGES reside on quay.io/skupper, but are not originally generated or
+# copied by this Makefile; still, when doing the copy operation, we can set 
them
+# to be read from a different MAIN_REPO
+$(other_copy): TARGET = $(shell echo "$@" | sed -e "s/_copy$$//" -e 's_.*/__' )
+$(other_copy):
+       # copy $(TARGET) from the other list
+       $(SKOPEO) copy --all $(TRANSFORM_OPTIONS) \
+               docker://$(MAIN_REPO)/$(TARGET) \
+               docker://$(COPY_REPO)/$(TARGET)
+
+# Here, the copy is from the original registry
+$(external_copy): TARGET = $(patsubst %_copy,%,$@)
+$(external_copy):
+       # copy $(TARGET) from the external list
+       $(SKOPEO) copy --all $(TRANSFORM_OPTIONS) \
+               docker://$(TARGET) \
+               docker://$(COPY_REPO)/$(TARGET)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/images/README.md 
new/skupper-1.8.3/test/images/README.md
--- old/skupper-1.8.2/test/images/README.md     2024-11-04 12:08:20.000000000 
+0100
+++ new/skupper-1.8.3/test/images/README.md     2025-01-08 19:00:52.000000000 
+0100
@@ -1,4 +1,4 @@
-# Images for external dependencies
+# Images for external test dependencies
 
 The Makefile on this directory allows for the manipulation of container images
 pertaining to external test dependencies, such as Mongo or quiver.
@@ -9,7 +9,7 @@
 
 The second operation was created in response to an image used by our tests that
 stopped getting updates, while the actual project continued to evolve.  It
-builds images from Dockerfile and pushes them into our Quay repo.
+builds images from Containerfiles and pushes them into our Quay repo.
 
 Finally, the third one also allows for the running of tests on disconnected
 clusters, which cannot access the original locations of these dependencies to
@@ -26,6 +26,10 @@
 contained on the Makefile.  Skupper images (such as the router or controller)
 are not copied by this operation.
 
+Note also that it is not a simple copy.  As Skupper can run on some older
+Kubernetes that do not support the OCI format, there are some transformations
+done during the copy as well.
+
 See the Makefile contents for information on how to execute the different
 operations.
 
@@ -33,5 +37,5 @@
 # skupper-test image
 
 Note that the `skupper-test` image used by Skupper integration is part of
-Skupper's own test code, so it's build by the main Makefile at ../.., and not
+Skupper's own test code, so it's built by the main Makefile at ../.., and not
 here.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/acceptance/custom/basic/basic.go 
new/skupper-1.8.3/test/integration/acceptance/custom/basic/basic.go
--- old/skupper-1.8.2/test/integration/acceptance/custom/basic/basic.go 
2024-11-04 12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/acceptance/custom/basic/basic.go 
2025-01-08 19:00:52.000000000 +0100
@@ -76,9 +76,21 @@
 
        const secretFile = "/tmp/public_basic_1_secret.yaml"
        if tokenType == "claim" {
-               err = pub1Cluster.VanClient.TokenClaimCreateFile(ctx, 
types.DefaultVanName, []byte(createOptsPublic.Password), 15*time.Minute, 1, 
secretFile)
+               err = utils.RetryError(3*time.Second, 5, func() error {
+                       err := pub1Cluster.VanClient.TokenClaimCreateFile(ctx, 
types.DefaultVanName, []byte(createOptsPublic.Password), 15*time.Minute, 1, 
secretFile)
+                       if err == nil {
+                               return nil
+                       }
+                       return err
+               })
        } else {
-               err = pub1Cluster.VanClient.ConnectorTokenCreateFile(ctx, 
types.DefaultVanName, secretFile)
+               err = utils.RetryError(3*time.Second, 5, func() error {
+                       err := 
pub1Cluster.VanClient.ConnectorTokenCreateFile(ctx, types.DefaultVanName, 
secretFile)
+                       if err == nil {
+                               return nil
+                       }
+                       return err
+               })
        }
        assert.Assert(t, err)
 
@@ -232,6 +244,7 @@
                        skip:       base.MultipleClusters(),
                        skipReason: SkipReasonIngressNone,
                        testSync:   true,
+                       tokenType:  "claim",
                        createOptsPublic: types.SiteConfigSpec{
                                SkupperName:         "",
                                RouterMode:          
string(types.TransportModeInterior),
@@ -297,9 +310,10 @@
                        },
                },
                {
-                       id:       "interiors-ingress-default",
-                       doc:      "Connecting two interiors with 
ingress=default (route if available or loadbalancer)",
-                       testSync: false,
+                       id:        "interiors-ingress-default",
+                       doc:       "Connecting two interiors with 
ingress=default (route if available or loadbalancer)",
+                       testSync:  false,
+                       tokenType: "claim",
                        createOptsPublic: types.SiteConfigSpec{
                                SkupperName:         "",
                                RouterMode:          
string(types.TransportModeInterior),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/examples/custom/hipstershop/hipstershop.go 
new/skupper-1.8.3/test/integration/examples/custom/hipstershop/hipstershop.go
--- 
old/skupper-1.8.2/test/integration/examples/custom/hipstershop/hipstershop.go   
    2024-11-04 12:08:20.000000000 +0100
+++ 
new/skupper-1.8.3/test/integration/examples/custom/hipstershop/hipstershop.go   
    2025-01-08 19:00:52.000000000 +0100
@@ -10,6 +10,7 @@
 
        "github.com/skupperproject/skupper/api/types"
        "github.com/skupperproject/skupper/pkg/utils"
+       "github.com/skupperproject/skupper/test/utils/arch"
        "github.com/skupperproject/skupper/test/utils/base"
        "github.com/skupperproject/skupper/test/utils/constants"
        "github.com/skupperproject/skupper/test/utils/k8s"
@@ -50,6 +51,11 @@
        prv1, err := testRunner.GetPrivateContext(1)
        assert.Assert(t, err)
 
+       // Hipstershop is currently supported only on amd64
+       //
+       // 
https://github.com/GoogleCloudPlatform/microservices-demo/issues/622#issuecomment-2066712947
+       assert.Assert(t, arch.Skip(t, pub1, pub2, prv1))
+
        // creating namespaces
        assert.Assert(t, pub1.CreateNamespace())
        assert.Assert(t, pub2.CreateNamespace())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/integration/examples/http/http.go 
new/skupper-1.8.3/test/integration/examples/http/http.go
--- old/skupper-1.8.2/test/integration/examples/http/http.go    2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/examples/http/http.go    2025-01-08 
19:00:52.000000000 +0100
@@ -643,7 +643,7 @@
                                        {
                                                Name:            "h1heybase",
                                                Image:           
"quay.io/skupper/hey",
-                                               Command:         
[]string{"hey_linux_amd64"},
+                                               Command:         
[]string{"/app/hey"},
                                                ImagePullPolicy: 
apiv1.PullAlways,
                                        },
                                },
@@ -809,7 +809,7 @@
        }
 }
 
-func runTests(t *testing.T, r base.ClusterTestRunner) {
+func runTests(t *testing.T, r *base.ClusterTestRunnerBase) {
        pubCluster1, err := r.GetPublicContext(1)
        assert.Assert(t, err)
 
@@ -891,7 +891,7 @@
        runHeyTestTable(t, pubCluster1)
 }
 
-func setup(ctx context.Context, t *testing.T, r base.ClusterTestRunner) {
+func setup(ctx context.Context, t *testing.T, r *base.ClusterTestRunnerBase) {
        prv1Cluster, err := r.GetPrivateContext(1)
        assert.Assert(t, err)
 
@@ -1003,13 +1003,18 @@
 
 }
 
-func Run(ctx context.Context, t *testing.T, r base.ClusterTestRunner) {
+func Run(ctx context.Context, t *testing.T, r *base.ClusterTestRunnerBase) {
        defer tearDown(ctx, r)
+       defer func() {
+               if t.Failed() {
+                       r.DumpTestInfo("TestHttp")
+               }
+       }()
        setup(ctx, t, r)
        runTests(t, r)
 }
 
-func tearDown(ctx context.Context, r base.ClusterTestRunner) {
+func tearDown(ctx context.Context, r *base.ClusterTestRunnerBase) {
        prv1Cluster, _ := r.GetPrivateContext(1)
 
        // Deleting Skupper services
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/examples/tcp_echo/tcp_echo.go 
new/skupper-1.8.3/test/integration/examples/tcp_echo/tcp_echo.go
--- old/skupper-1.8.2/test/integration/examples/tcp_echo/tcp_echo.go    
2024-11-04 12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/examples/tcp_echo/tcp_echo.go    
2025-01-08 19:00:52.000000000 +0100
@@ -177,13 +177,17 @@
        endTime = 
time.Now().Add(constants.ImagePullingAndResourceCreationTimeout)
 
        job, err := k8s.WaitForJob(pub1Cluster.Namespace, 
pub1Cluster.VanClient.KubeClient, jobName, endTime.Sub(time.Now()))
+       if err != nil {
+               pub1Cluster.KubectlExec("logs job/" + jobName)
+       }
        assert.Assert(t, err)
-       pub1Cluster.KubectlExec("logs job/" + jobName)
        k8s.AssertJob(t, job)
 
        job, err = k8s.WaitForJob(prv1Cluster.Namespace, 
prv1Cluster.VanClient.KubeClient, jobName, endTime.Sub(time.Now()))
+       if err != nil {
+               prv1Cluster.KubectlExec("logs job/" + jobName)
+       }
        assert.Assert(t, err)
-       prv1Cluster.KubectlExec("logs job/" + jobName)
        k8s.AssertJob(t, job)
 
        netcatJobName := fmt.Sprintf("netcat-%s", svc.Address)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/performance/amqp_test.go 
new/skupper-1.8.3/test/integration/performance/amqp_test.go
--- old/skupper-1.8.2/test/integration/performance/amqp_test.go 2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/performance/amqp_test.go 2025-01-08 
19:00:52.000000000 +0100
@@ -14,6 +14,7 @@
        "testing"
        "time"
 
+       "github.com/skupperproject/skupper/pkg/images"
        "github.com/skupperproject/skupper/test/integration/performance/common"
        "github.com/skupperproject/skupper/test/utils/base"
        "github.com/skupperproject/skupper/test/utils/k8s"
@@ -222,7 +223,7 @@
 
 func getAmqpDeployment() *appsv1.Deployment {
        dep, _ := k8s.NewDeployment("amqp-server", "", k8s.DeploymentOpts{
-               Image:  "quay.io/skupper/skupper-router:2.6.1",
+               Image:  images.GetRouterImageName(),
                Labels: map[string]string{"app": "amqp-server"},
        })
        return dep
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/performance/common/perfrunner.go 
new/skupper-1.8.3/test/integration/performance/common/perfrunner.go
--- old/skupper-1.8.2/test/integration/performance/common/perfrunner.go 
2024-11-04 12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/performance/common/perfrunner.go 
2025-01-08 19:00:52.000000000 +0100
@@ -11,6 +11,7 @@
        "github.com/skupperproject/skupper/api/types"
        "github.com/skupperproject/skupper/pkg/kube"
        "github.com/skupperproject/skupper/pkg/utils"
+       "github.com/skupperproject/skupper/test/utils/arch"
        "github.com/skupperproject/skupper/test/utils/base"
        "github.com/skupperproject/skupper/test/utils/constants"
        "github.com/skupperproject/skupper/test/utils/k8s"
@@ -69,6 +70,18 @@
        }
 
        for _, job := range app.Client.Jobs {
+               if job.Job.Labels["type"] == "wrk2" {
+                       // wrk2 is not available for arm64
+                       // https://github.com/giltene/wrk2/issues/104
+                       err, skip := arch.Check(clientCluster)
+                       if skip {
+                               logger.Printf("! Skipping job %q: %v", 
job.Name, err)
+                               continue
+                       }
+                       if err != nil {
+                               return err
+                       }
+               }
                resultInfo := resultInfo{job: job}
                stepLog.Printf("- Running client job %s at %s", job.Name, 
clientCluster.Namespace)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/performance/common/setup.go 
new/skupper-1.8.3/test/integration/performance/common/setup.go
--- old/skupper-1.8.2/test/integration/performance/common/setup.go      
2024-11-04 12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/performance/common/setup.go      
2025-01-08 19:00:52.000000000 +0100
@@ -22,6 +22,7 @@
        "github.com/skupperproject/skupper/pkg/kube"
        pkgutils "github.com/skupperproject/skupper/pkg/utils"
        "github.com/skupperproject/skupper/test/utils"
+       "github.com/skupperproject/skupper/test/utils/arch"
        "github.com/skupperproject/skupper/test/utils/base"
        "github.com/skupperproject/skupper/test/utils/constants"
        v1 "k8s.io/api/core/v1"
@@ -37,6 +38,13 @@
        debug                  bool
 )
 
+// Tests do not have access to common.testRunner, so they can call this
+// function to check on cluster architectures, and skip accordingly.
+func CheckArch(t *testing.T) error {
+       err := arch.Skip(t, testRunner.ClusterContexts...)
+       return err
+}
+
 func DebugMode() bool {
        return debug
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/performance/http_test.go 
new/skupper-1.8.3/test/integration/performance/http_test.go
--- old/skupper-1.8.2/test/integration/performance/http_test.go 2024-11-04 
12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/performance/http_test.go 2025-01-08 
19:00:52.000000000 +0100
@@ -324,7 +324,7 @@
        for _, clients := range settings.clients {
                // wrk job
                jobWrkName := fmt.Sprintf("%s-wrk-clients-%d", jobPrefix, 
clients)
-               labelsWrk := map[string]string{"job": jobWrkName}
+               labelsWrk := map[string]string{"job": jobWrkName, "type": "wrk"}
                job := &batchv1.Job{
                        ObjectMeta: metav1.ObjectMeta{Name: jobWrkName, Labels: 
labelsWrk},
                        Spec: batchv1.JobSpec{
@@ -355,7 +355,7 @@
                        log.Printf("rate is required for wrk2 - setting to 
(default) %d", wrk2Rate)
                }
                jobWrk2Name := fmt.Sprintf("%s-wrk2-rate-%d-clients-%d", 
jobPrefix, wrk2Rate, clients)
-               labelsWrk2 := map[string]string{"job": jobWrk2Name}
+               labelsWrk2 := map[string]string{"job": jobWrk2Name, "type": 
"wrk2"}
                job = &batchv1.Job{
                        ObjectMeta: metav1.ObjectMeta{Name: jobWrk2Name, 
Labels: labelsWrk2},
                        Spec: batchv1.JobSpec{
@@ -374,6 +374,7 @@
                                },
                        },
                }
+
                jobs = append(jobs, common.JobInfo{
                        Name:    jobWrk2Name,
                        Clients: clients,
@@ -382,7 +383,7 @@
 
                // hey job
                jobHeyName := fmt.Sprintf("%s-hey-clients-%d", jobPrefix, 
clients)
-               labelsHey := map[string]string{"job": jobHeyName}
+               labelsHey := map[string]string{"job": jobHeyName, "type": "hey"}
                heyArgs := []string{"-z", strconv.Itoa(settings.duration) + 
"s", "-c", strconv.Itoa(clients)}
                if settings.rate > 0 {
                        heyArgs = append(heyArgs, "-q", 
strconv.Itoa(settings.rate))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/skupper-1.8.2/test/integration/performance/postgres_test.go 
new/skupper-1.8.3/test/integration/performance/postgres_test.go
--- old/skupper-1.8.2/test/integration/performance/postgres_test.go     
2024-11-04 12:08:20.000000000 +0100
+++ new/skupper-1.8.3/test/integration/performance/postgres_test.go     
2025-01-08 19:00:52.000000000 +0100
@@ -45,6 +45,10 @@
 }
 
 func TestPostgres(t *testing.T) {
+       // TestPostgres is currently not functional for ARM
+       // https://github.com/skupperproject/skupper/issues/1650
+       common.CheckArch(t)
+
        settings := parsePostgresSettings()
        p := &PostgresTest{
                Name:        "postgres",
@@ -61,6 +65,7 @@
                LatencyUnit:    common.LatencyUnitMs,
        }
        assert.Assert(t, common.RunPerformanceTest(p))
+
 }
 
 func (p *PostgresTest) App() common.PerformanceApp {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/utils/arch/k8s.go 
new/skupper-1.8.3/test/utils/arch/k8s.go
--- old/skupper-1.8.2/test/utils/arch/k8s.go    1970-01-01 01:00:00.000000000 
+0100
+++ new/skupper-1.8.3/test/utils/arch/k8s.go    2025-01-08 19:00:52.000000000 
+0100
@@ -0,0 +1,55 @@
+package arch
+
+import (
+       "context"
+       "fmt"
+       "testing"
+       "time"
+
+       "github.com/skupperproject/skupper/test/utils/base"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// If the target clusters are found to contain any non-amd64 nodes, return 
true.
+//
+// Notice that only the cluster is checked to be amd64; if the VM needs 
checked,
+// use build flags or some other technique.
+//
+// Usage: check first skip; only check err if skip is false.  If skip is true, 
error
+// will be non-nil, with information on why skipping
+//
+// TODO: make it more granular, allow for hibrid clusters?
+// TODO: allow for list of accepted archs?
+func Check(clusters ...*base.ClusterContext) (err error, skip bool) {
+
+       ctx, cancel := context.WithTimeout(context.Background(), time.Minute*10)
+       defer cancel()
+
+       for _, c := range clusters {
+               list, err := c.VanClient.KubeClient.CoreV1().Nodes().List(ctx, 
v1.ListOptions{})
+               if err != nil {
+                       return err, false
+               }
+               for _, node := range list.Items {
+                       arch := node.Labels["beta.kubernetes.io/arch"]
+                       if arch != "amd64" {
+                               return fmt.Errorf(
+                                       "at least one cluster node is not amd64 
-- skipping (%s at %s is %q)",
+                                       node.Name,
+                                       c.VanClient.RestConfig.Host,
+                                       arch,
+                               ), true
+                       }
+               }
+       }
+       return nil, false
+}
+
+// Calls arch.Check, and skip the test as needed
+func Skip(t *testing.T, clusters ...*base.ClusterContext) error {
+       err, skip := Check(clusters...)
+       if skip {
+               t.Skipf("%v", err)
+       }
+       return err
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/utils/k8s/job.go 
new/skupper-1.8.3/test/utils/k8s/job.go
--- old/skupper-1.8.2/test/utils/k8s/job.go     2024-11-04 12:08:20.000000000 
+0100
+++ new/skupper-1.8.3/test/utils/k8s/job.go     2025-01-08 19:00:52.000000000 
+0100
@@ -175,19 +175,29 @@
                case <-timeoutCh:
                        return nil, fmt.Errorf("Timeout: Job is still active: 
%s", jobName)
                case <-tick:
-                       job, _ := jobsClient.Get(context.TODO(), jobName, 
metav1.GetOptions{})
+                       job, err := jobsClient.Get(context.TODO(), jobName, 
metav1.GetOptions{})
+
+                       if err != nil {
+                               return nil, err // Handle the error
+                       }
 
                        if job.Status.Active > 0 {
                                fmt.Println("Job is still active")
                        } else if len(job.Status.Conditions) > 0 {
-                               if job.Status.Conditions[0].Type == 
batchv1.JobComplete {
-                                       fmt.Println("Job Successful!")
-                                       return job, nil
-                               } else if job.Status.Conditions[0].Type == 
batchv1.JobFailed {
-                                       statusJson, _ := 
json.Marshal(job.Status)
-                                       fmt.Printf("Job failed?, status = 
%v\n", string(statusJson))
-                                       return job, fmt.Errorf("Job failed. 
Status: %s", string(statusJson))
+                               for _, condition := range job.Status.Conditions 
{
+                                       switch condition.Type {
+                                       case batchv1.JobComplete:
+                                               fmt.Println("Job Successful!")
+                                               return job, nil
+                                       case batchv1.JobFailed:
+                                               statusJson, _ := 
json.Marshal(job.Status)
+                                               fmt.Printf("Job failed?, status 
= %v\n", string(statusJson))
+                                               return job, fmt.Errorf("Job 
failed. Status: %s", string(statusJson))
+                                       }
                                }
+                               // No terminal condition detected above
+                               statusJson, _ := json.Marshal(job.Status)
+                               fmt.Printf("Job is not active, but it is 
neither successful nor failed.  Status:\n%v\n", string(statusJson))
                        } else {
                                fmt.Println("Waiting on job condition")
                        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/skupper-1.8.2/test/utils/tools/curl.go 
new/skupper-1.8.3/test/utils/tools/curl.go
--- old/skupper-1.8.2/test/utils/tools/curl.go  2024-11-04 12:08:20.000000000 
+0100
+++ new/skupper-1.8.3/test/utils/tools/curl.go  2025-01-08 19:00:52.000000000 
+0100
@@ -204,7 +204,7 @@
                },
                Spec: v1.PodSpec{
                        Containers: []v1.Container{
-                               {Name: "curl", Image: "curlimages/curl", 
Command: strings.Split("tail -f /dev/null", " ")},
+                               {Name: "curl", Image: "quay.io/curl/curl", 
Command: strings.Split("tail -f /dev/null", " ")},
                        },
                        RestartPolicy:                 v1.RestartPolicyAlways,
                        TerminationGracePeriodSeconds: &terminationPeriodSecs,

++++++ skupper.obsinfo ++++++
--- /var/tmp/diff_new_pack.VH5S0Z/_old  2025-01-09 15:12:33.301034319 +0100
+++ /var/tmp/diff_new_pack.VH5S0Z/_new  2025-01-09 15:12:33.301034319 +0100
@@ -1,5 +1,5 @@
 name: skupper
-version: 1.8.2
-mtime: 1730718500
-commit: 149f4a5588c532d6ab1fc489b19ca24633e521e7
+version: 1.8.3
+mtime: 1736359252
+commit: f9c88e4e90f0a7f916e9b5d29e8dce5d2340f78e
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/skupper/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.skupper.new.1881/vendor.tar.gz differ: char 12, 
line 1

Reply via email to