commit skupper for openSUSE:Factory
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_buildservice@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#issueco... + 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
participants (1)
-
Source-Sync