Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package suseconnect-ng for openSUSE:Factory checked in at 2022-08-23 14:25:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/suseconnect-ng (Old) and /work/SRC/openSUSE:Factory/.suseconnect-ng.new.2083 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "suseconnect-ng" Tue Aug 23 14:25:55 2022 rev:10 rq:993339 version:0.0.9~git5.75890b6 Changes: -------- --- /work/SRC/openSUSE:Factory/suseconnect-ng/suseconnect-ng.changes 2022-04-20 16:54:35.122469221 +0200 +++ /work/SRC/openSUSE:Factory/.suseconnect-ng.new.2083/suseconnect-ng.changes 2022-08-23 14:26:35.415218665 +0200 @@ -1,0 +2,19 @@ +Fri Aug 05 13:33:05 UTC 2022 - jan.s...@zerebecki.de + +- Update to version 0.0.9~git5.75890b6: + * Don't run keepalive on reboot + * Use system-wide proxy settings (bsc#1200994) + * Add customer information about keepalive calls + * Add timer for SUSEConnect --keepalive (bsc#1196076) + * Add --keepalive to manpage + * Added support for the System-Token header + * Add Keepalive command line option + * Print nested zypper errors (bsc#1200803) + * Fix migration json error with SMT (bsc#1198625) + * Add option to run local scc tests + * Switch to jenkins-hosted credentials + * Fix "VCS stamping" problem + * Add missing import + * Remove redundant code + add comment + +------------------------------------------------------------------- Old: ---- connect-ng-0.0.8~git2.368ea44.tar.xz New: ---- connect-ng-0.0.9~git5.75890b6.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ suseconnect-ng.spec ++++++ --- /var/tmp/diff_new_pack.T8x4Yi/_old 2022-08-23 14:26:36.679221447 +0200 +++ /var/tmp/diff_new_pack.T8x4Yi/_new 2022-08-23 14:26:36.683221455 +0200 @@ -23,7 +23,7 @@ %global test_hwinfo 0 Name: suseconnect-ng -Version: 0.0.8~git2.368ea44 +Version: 0.0.9~git5.75890b6 Release: 0 URL: https://github.com/SUSE/connect-ng License: LGPL-2.1-or-later @@ -31,7 +31,6 @@ Group: System/Management Source: connect-ng-%{version}.tar.xz Source1: %name-rpmlintrc -BuildRequires: git BuildRequires: go >= 1.16 BuildRequires: golang-packaging BuildRequires: ruby-devel @@ -106,6 +105,8 @@ %prep %setup -q -n connect-ng-%{version} +# keep git metadata but don't use it for "VCS stamping" +mv .git .git.bak %build find %_builddir/.. @@ -133,10 +134,62 @@ install -D -m 644 %_builddir/go/src/%import_path/man/zypper-migration.8 %buildroot/%_mandir/man8/zypper-migration.8 install -D -m 644 %_builddir/go/src/%import_path/man/zypper-search-packages.8 %buildroot/%_mandir/man8/zypper-search-packages.8 +# Install the SUSEConnect --keepalive timer and service. +install -D -m 644 %_builddir/go/src/%import_path/suseconnect-keepalive.timer %buildroot/%_unitdir/suseconnect-keepalive.timer +install -D -m 644 %_builddir/go/src/%import_path/suseconnect-keepalive.service %buildroot/%_unitdir/suseconnect-keepalive.service +ln -sf service %buildroot/%_sbindir/rcsuseconnect-keepalive + find %_builddir/.. # we currently do not ship the source for any go module rm -rf %buildroot/usr/share/go +%pre +%service_add_pre suseconnect-keepalive.service suseconnect-keepalive.timer + +# in pre blocks the old version is still installed. This way we can detect +# if --keepalive was already present before +kainfo=0 +helptext=$(SUSEConnect --help) +if [ $? -eq 0 ]; then + echo "$helptext" | grep -q keepalive + kainfo=$? +fi + +if [ $kainfo -ne 0 ]; then + cat << EOF +Empowering you with enriched system visibility in the SUSE Customer Center + +SUSE is committed to helping provide better insights into the consumption of +SUSE subscriptions regardless of where they are running; physical or virtual, +on-prem or in the cloud. + +SUSE has been working on several improvements to the SUSE Customer Center (SCC), +RMT, and SUSE Manager to provide a clearer picture of your system landscape: + +- SUSE Manager v4.1+ now sends system information to SCC. +- SCC now captures which products are activated on systems that sit behind RMT + or SMT. +- This update will enable your system to "ping" SCC/RMT daily to + confirm the system's active status. This will help you identify or filter out + systems in SCC that are no longer running or decommissioned. As always, the + choice is yours, you can disable the daily ping by disabling the + suseconnect-keepalive systemd timer. + +We will continue improving our products to make it easier for you to view and +manage your subscription consumption. As always, we'd love to hear your feedback +about these improvements and any ideas you might have. +EOF +fi + +%post +%service_add_post suseconnect-keepalive.service suseconnect-keepalive.timer + +%preun +%service_del_preun suseconnect-keepalive.service suseconnect-keepalive.timer + +%postun +%service_del_postun suseconnect-keepalive.service suseconnect-keepalive.timer + %check %gotest -v %import_path/internal/connect %{?test_hwinfo_args} %gotest -v %import_path/suseconnect @@ -148,9 +201,12 @@ %_bindir/suseconnect %_bindir/SUSEConnect %_sbindir/SUSEConnect +%_sbindir/rcsuseconnect-keepalive /usr/lib/zypper/commands %_mandir/man8/* %_mandir/man5/* +%_unitdir/suseconnect-keepalive.service +%_unitdir/suseconnect-keepalive.timer %files -n libsuseconnect %license LICENSE LICENSE.LGPL ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.T8x4Yi/_old 2022-08-23 14:26:36.731221561 +0200 +++ /var/tmp/diff_new_pack.T8x4Yi/_new 2022-08-23 14:26:36.735221570 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/SUSE/connect-ng.git</param> - <param name="changesrevision">7497adf2078f1d8f9eb51ef90ec61f7bfb46c848</param></service></servicedata> + <param name="changesrevision">75890b6d6cb41ce623cec1fd77f3c899e2625f88</param></service></servicedata> (No newline at EOF) ++++++ connect-ng-0.0.8~git2.368ea44.tar.xz -> connect-ng-0.0.9~git5.75890b6.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/FETCH_HEAD new/connect-ng-0.0.9~git5.75890b6/.git/FETCH_HEAD --- old/connect-ng-0.0.8~git2.368ea44/.git/FETCH_HEAD 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.git/FETCH_HEAD 2022-08-03 09:54:35.000000000 +0200 @@ -1 +1 @@ -368ea44344a170c3bdaf4dba6e69a3ec44de1be1 branch 'main' of https://github.com/SUSE/connect-ng +75890b6d6cb41ce623cec1fd77f3c899e2625f88 branch 'main' of https://github.com/SUSE/connect-ng diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/ORIG_HEAD new/connect-ng-0.0.9~git5.75890b6/.git/ORIG_HEAD --- old/connect-ng-0.0.8~git2.368ea44/.git/ORIG_HEAD 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.git/ORIG_HEAD 2022-08-03 09:54:35.000000000 +0200 @@ -1 +1 @@ -368ea44344a170c3bdaf4dba6e69a3ec44de1be1 +75890b6d6cb41ce623cec1fd77f3c899e2625f88 Binary files old/connect-ng-0.0.8~git2.368ea44/.git/index and new/connect-ng-0.0.9~git5.75890b6/.git/index differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/logs/HEAD new/connect-ng-0.0.9~git5.75890b6/.git/logs/HEAD --- old/connect-ng-0.0.8~git2.368ea44/.git/logs/HEAD 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.git/logs/HEAD 2022-08-03 09:54:35.000000000 +0200 @@ -22,3 +22,5 @@ 16545bf627186d6c3e0754ecdcf8aa5e080877fd 16545bf627186d6c3e0754ecdcf8aa5e080877fd jan_osc <jan_osc@localhost.(none)> 1649854761 +0200 reset: moving to main 16545bf627186d6c3e0754ecdcf8aa5e080877fd 368ea44344a170c3bdaf4dba6e69a3ec44de1be1 jan_osc <jan_osc@localhost.(none)> 1650442680 +0200 merge origin/main: Fast-forward 368ea44344a170c3bdaf4dba6e69a3ec44de1be1 368ea44344a170c3bdaf4dba6e69a3ec44de1be1 jan_osc <jan_osc@localhost.(none)> 1650442681 +0200 reset: moving to main +368ea44344a170c3bdaf4dba6e69a3ec44de1be1 75890b6d6cb41ce623cec1fd77f3c899e2625f88 jan_osc <jan_osc@localhost.(none)> 1659706384 +0200 merge origin/main: Fast-forward +75890b6d6cb41ce623cec1fd77f3c899e2625f88 75890b6d6cb41ce623cec1fd77f3c899e2625f88 jan_osc <jan_osc@localhost.(none)> 1659706384 +0200 reset: moving to main diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/logs/refs/heads/main new/connect-ng-0.0.9~git5.75890b6/.git/logs/refs/heads/main --- old/connect-ng-0.0.8~git2.368ea44/.git/logs/refs/heads/main 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.git/logs/refs/heads/main 2022-08-03 09:54:35.000000000 +0200 @@ -13,3 +13,4 @@ 33e58472fd2f39bc963859cbe5892fb47fd6b9b6 3ef988ed2feed23430e8f0d3f58d2a45301932a7 jan_osc <jan_osc@localhost.(none)> 1648123790 +0100 merge origin/main: Fast-forward 3ef988ed2feed23430e8f0d3f58d2a45301932a7 16545bf627186d6c3e0754ecdcf8aa5e080877fd jan_osc <jan_osc@localhost.(none)> 1649854761 +0200 merge origin/main: Fast-forward 16545bf627186d6c3e0754ecdcf8aa5e080877fd 368ea44344a170c3bdaf4dba6e69a3ec44de1be1 jan_osc <jan_osc@localhost.(none)> 1650442680 +0200 merge origin/main: Fast-forward +368ea44344a170c3bdaf4dba6e69a3ec44de1be1 75890b6d6cb41ce623cec1fd77f3c899e2625f88 jan_osc <jan_osc@localhost.(none)> 1659706384 +0200 merge origin/main: Fast-forward diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/logs/refs/remotes/origin/main new/connect-ng-0.0.9~git5.75890b6/.git/logs/refs/remotes/origin/main --- old/connect-ng-0.0.8~git2.368ea44/.git/logs/refs/remotes/origin/main 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.git/logs/refs/remotes/origin/main 2022-08-03 09:54:35.000000000 +0200 @@ -12,3 +12,4 @@ 33e58472fd2f39bc963859cbe5892fb47fd6b9b6 3ef988ed2feed23430e8f0d3f58d2a45301932a7 jan_osc <jan_osc@localhost.(none)> 1648123789 +0100 fetch --tags: fast-forward 3ef988ed2feed23430e8f0d3f58d2a45301932a7 16545bf627186d6c3e0754ecdcf8aa5e080877fd jan_osc <jan_osc@localhost.(none)> 1649854760 +0200 fetch --tags: fast-forward 16545bf627186d6c3e0754ecdcf8aa5e080877fd 368ea44344a170c3bdaf4dba6e69a3ec44de1be1 jan_osc <jan_osc@localhost.(none)> 1650442680 +0200 fetch --tags: fast-forward +368ea44344a170c3bdaf4dba6e69a3ec44de1be1 75890b6d6cb41ce623cec1fd77f3c899e2625f88 jan_osc <jan_osc@localhost.(none)> 1659706384 +0200 fetch --tags: fast-forward Binary files old/connect-ng-0.0.8~git2.368ea44/.git/objects/pack/pack-8df2cb00d9ea6c83d0c9f29bcf2330ec25f66fcd.idx and new/connect-ng-0.0.9~git5.75890b6/.git/objects/pack/pack-8df2cb00d9ea6c83d0c9f29bcf2330ec25f66fcd.idx differ Binary files old/connect-ng-0.0.8~git2.368ea44/.git/objects/pack/pack-8df2cb00d9ea6c83d0c9f29bcf2330ec25f66fcd.pack and new/connect-ng-0.0.9~git5.75890b6/.git/objects/pack/pack-8df2cb00d9ea6c83d0c9f29bcf2330ec25f66fcd.pack differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/refs/heads/main new/connect-ng-0.0.9~git5.75890b6/.git/refs/heads/main --- old/connect-ng-0.0.8~git2.368ea44/.git/refs/heads/main 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.git/refs/heads/main 2022-08-03 09:54:35.000000000 +0200 @@ -1 +1 @@ -368ea44344a170c3bdaf4dba6e69a3ec44de1be1 +75890b6d6cb41ce623cec1fd77f3c899e2625f88 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/refs/remotes/origin/main new/connect-ng-0.0.9~git5.75890b6/.git/refs/remotes/origin/main --- old/connect-ng-0.0.8~git2.368ea44/.git/refs/remotes/origin/main 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.git/refs/remotes/origin/main 2022-08-03 09:54:35.000000000 +0200 @@ -1 +1 @@ -368ea44344a170c3bdaf4dba6e69a3ec44de1be1 +75890b6d6cb41ce623cec1fd77f3c899e2625f88 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.git/refs/tags/v0.0.9 new/connect-ng-0.0.9~git5.75890b6/.git/refs/tags/v0.0.9 --- old/connect-ng-0.0.8~git2.368ea44/.git/refs/tags/v0.0.9 1970-01-01 01:00:00.000000000 +0100 +++ new/connect-ng-0.0.9~git5.75890b6/.git/refs/tags/v0.0.9 2022-08-03 09:54:35.000000000 +0200 @@ -0,0 +1 @@ +b360d2479a596ab48d5614ee7457efd8dcf6d67b diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/.gitignore new/connect-ng-0.0.9~git5.75890b6/.gitignore --- old/connect-ng-0.0.8~git2.368ea44/.gitignore 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/.gitignore 2022-08-03 09:54:35.000000000 +0200 @@ -1,2 +1,3 @@ out internal/connect/version.txt +connect-ruby diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/Makefile new/connect-ng-0.0.9~git5.75890b6/Makefile --- old/connect-ng-0.0.8~git2.368ea44/Makefile 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/Makefile 2022-08-03 09:54:35.000000000 +0200 @@ -20,6 +20,13 @@ test-yast: build-so docker build -t go-connect-test-yast -f Dockerfile.yast . && docker run -t go-connect-test-yast +test-scc: connect-ruby + docker build -t connect.ng-sle15sp3 -f integration/Dockerfile.ng-sle15sp3 . + docker run --privileged --rm -t connect.ng-sle15sp3 ./integration/run.sh + +connect-ruby: + git clone https://github.com/SUSE/connect connect-ruby + gofmt: @if [ ! -z "$$(gofmt -l ./)" ]; then echo "Formatting errors..."; gofmt -d ./; exit 1; fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/integration/Dockerfile.ng-sle15sp3 new/connect-ng-0.0.9~git5.75890b6/integration/Dockerfile.ng-sle15sp3 --- old/connect-ng-0.0.8~git2.368ea44/integration/Dockerfile.ng-sle15sp3 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/integration/Dockerfile.ng-sle15sp3 2022-08-03 09:54:35.000000000 +0200 @@ -3,8 +3,6 @@ ENV PRODUCT SLE_15_SP3 ENV BUILT_AT "Tue Jul 13 15:32 CET 2021" -RUN useradd --no-log-init --create-home scc - # Remember to drop docker caches if any of these change RUN zypper ar http://download.suse.de/ibs/SUSE/Products/SLE-Module-Basesystem/15-SP3/x86_64/product base &&\ zypper ar http://download.suse.de/ibs/SUSE/Updates/SLE-Module-Basesystem/15-SP3/x86_64/update base-updates &&\ @@ -20,8 +18,8 @@ vim osc hwinfo libx86emu3 zypper-migration-plugin sudo awk curl \ obs-service-tar_scm obs-service-recompress obs-service-extract_file obs-service-set_version obs-service-format_spec_file -RUN wget http://username:passw...@gaffer.suse.de:9999/files/.regcode -O ~/.regcode -RUN wget http://username:passw...@gaffer.suse.de:9999/files/.oscrc -O ~/.oscrc +RUN wget --no-check-certificate https://ci.suse.de/job/scc-connect-ng-config/lastBuild/artifact/.regcodes -O ~/.regcodes +RUN wget --no-check-certificate https://ci.suse.de/job/scc-connect-ng-config/lastBuild/artifact/.oscrc -O ~/.oscrc RUN echo 'gem: --no-ri --no-rdoc' > /etc/gemrc && \ gem install bundler --no-document @@ -35,10 +33,8 @@ RUN bundle config jobs $(nproc) && \ bundle install ADD connect-ruby/. /tmp/connect -RUN chown -R scc /tmp/connect RUN mkdir /tmp/connect-ng WORKDIR /tmp/connect-ng ADD . /tmp/connect-ng -RUN chown -R scc /tmp/connect-ng diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/integration/run.sh new/connect-ng-0.0.9~git5.75890b6/integration/run.sh --- old/connect-ng-0.0.8~git2.368ea44/integration/run.sh 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/integration/run.sh 2022-08-03 09:54:35.000000000 +0200 @@ -13,7 +13,7 @@ head=$(git rev-list -n1 HEAD) mkdir osc-package cd osc-package -osc co -o . 'systemsmanagement:SCC/suseconnect-ng' +osc -A https://api.opensuse.org co -o . 'systemsmanagement:SCC/suseconnect-ng' cp ../_service ./ sed -i "s|https://github.com/SUSE/connect-ng.git|file://$remote|g" _service sed -i "s|main|$head|g" _service @@ -37,4 +37,8 @@ rm bin/SUSEConnect # the tests match the exact version defined in the ruby code, replace it with ours sed -i "s|VERSION = '[^']*'|VERSION = '$shortversion'|g" lib/suse/connect/version.rb +# load test regcodes into env vars +set -a +. ~/.regcodes +set +a cucumber diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/api.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/api.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/api.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/api.go 2022-08-03 09:54:35.000000000 +0200 @@ -14,13 +14,13 @@ return "", "", err } var creds struct { - Login string `json:"login"` - Passoword string `json:"password"` + Login string `json:"login"` + Password string `json:"password"` } if err = json.Unmarshal(resp, &creds); err != nil { return "", "", JSONError{err} } - return creds.Login, creds.Passoword, nil + return creds.Login, creds.Password, nil } func upToDate() bool { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/api_test.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/api_test.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/api_test.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/api_test.go 2022-08-03 09:54:35.000000000 +0200 @@ -8,8 +8,11 @@ ) func TestAnnounceSystem(t *testing.T) { + createTestCredentials("", "", t) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") + w.Header().Set("System-Token", "token") io.WriteString(w, `{"login":"test-user","password":"test-password"}`) })) defer ts.Close() @@ -25,6 +28,15 @@ if password != "test-password" { t.Errorf("Expected password: \"test-password\", got: \"%s\"", password) } + + // System token should have been updated. + creds, err := getCredentials() + if err != nil { + t.Fatalf("Unexpected error: %s", err) + } + if creds.SystemToken != "token" { + t.Fatalf("Unexpected token '%v', should have been 'token'", creds.SystemToken) + } } func TestGetActivations(t *testing.T) { @@ -267,3 +279,25 @@ t.Fatalf("len(migrations) == %d, expected 2", len(migrations)) } } + +func TestProductMigrationsSMT(t *testing.T) { + createTestCredentials("", "", t) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write(readTestFile("migrations-smt.json", t)) + })) + defer ts.Close() + CFG.BaseURL = ts.URL + + migrations, err := productMigrations(nil) + if err != nil { + t.Fatal(err) + } + if len(migrations) != 1 { + t.Fatalf("len(migrations) == %d, expected 1", len(migrations)) + } + gotID := migrations[0][0].ID + expectedID := 101361 + if gotID != expectedID { + t.Fatalf("Got ID: %d, expected: %d", gotID, expectedID) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/client.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/client.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/client.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/client.go 2022-08-03 09:54:35.000000000 +0200 @@ -200,6 +200,18 @@ return updateSystem(sysInfoBody) } +// SendKeepAlivePing updates the system information on the server +func SendKeepAlivePing() error { + if !IsRegistered() { + return ErrPingFromUnregistered + } + err := UpdateSystem("", "") + if err == nil { + Info.Print(bold(greenText("\nSuccessfully updated system"))) + } + return err +} + // announceOrUpdate Announces the system to the server, receiving and storing its // credentials. When already announced, sends the current hardware details to the server func announceOrUpdate() error { @@ -215,7 +227,7 @@ if err != nil { return err } - return writeSystemCredentials(login, password) + return writeSystemCredentials(login, password, "") } // IsRegistered returns true if there is a valid credentials file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/connection.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/connection.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/connection.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/connection.go 2022-08-03 09:54:35.000000000 +0200 @@ -8,6 +8,7 @@ "net/http" "net/http/httputil" "net/url" + "strings" "time" ) @@ -52,6 +53,14 @@ } // REVISIT "Accept-Encoding" - disable gzip commpression on debug? req.Header.Add("User-Agent", appName+"/"+GetShortenedVersion()) + + // Pass the current system token. + creds, err := getCredentials() + token := "" + if err == nil { + token = creds.SystemToken + } + req.Header.Add("System-Token", token) } func addAuthHeader(req *http.Request, auth authType) error { @@ -97,13 +106,6 @@ func callHTTP(verb, path string, body []byte, query map[string]string, auth authType) ([]byte, error) { setupHTTPClient() - if httpclient == nil { - // use defaults from DefaultTransport - tr := http.DefaultTransport.(*http.Transport).Clone() - tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: CFG.Insecure} - tr.Proxy = proxyWithAuth - httpclient = &http.Client{Transport: tr, Timeout: 60 * time.Second} - } req, err := http.NewRequest(verb, CFG.BaseURL, bytes.NewReader(body)) if err != nil { return nil, err @@ -132,6 +134,13 @@ } defer resp.Body.Close() + // For each request SCC might update the System token for a given system. + // This will be given through the `System-Token` header, so we have to grab + // this here and store it for the next request. + if err := handleSystemToken(resp.Header.Get("System-Token")); err != nil { + Debug.Printf("system-token: %s\n", err) + } + if isLoggerEnabled(Debug) { respBlob, _ := httputil.DumpResponse(resp, true) Debug.Printf("%s\n", respBlob) @@ -148,6 +157,24 @@ return resBody, nil } +// handleSystemToken stores the given token into the system credentials file +// unless it's blank. +func handleSystemToken(token string) error { + token = strings.TrimSpace(token) + if token == "" { + return nil + } + + creds, err := getCredentials() + if err != nil { + return err + } + + creds.SystemToken = token + return creds.write() +} + +// ReloadCertPool triggers reload of internals CA cert pool func ReloadCertPool() error { // TODO: update when https://github.com/golang/go/issues/41888 is fixed httpclient = nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/credentials.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/credentials.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/credentials.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/credentials.go 2022-08-03 09:54:35.000000000 +0200 @@ -17,21 +17,23 @@ ) var ( - userMatch = regexp.MustCompile(`(?m)^\s*username\s*=\s*(\S+)\s*$`) - passMatch = regexp.MustCompile(`(?m)^\s*password\s*=\s*(\S+)\s*$`) - curlrcMatch = regexp.MustCompile(`^\s*-*proxy-user[ =]*"(.+):(.+)"\s*$`) + userMatch = regexp.MustCompile(`(?m)^\s*username\s*=\s*(\S+)\s*$`) + passMatch = regexp.MustCompile(`(?m)^\s*password\s*=\s*(\S+)\s*$`) + systemTokenMatch = regexp.MustCompile(`(?m)^\s*system_token\s*=\s*(\S+)\s*$`) + curlrcMatch = regexp.MustCompile(`^\s*-*proxy-user[ =]*"(.+):(.+)"\s*$`) ) // Credentials stores the SCC or service credentials type Credentials struct { - Filename string `json:"file"` - Username string `json:"username"` - Password string `json:"password"` + Filename string `json:"file"` + Username string `json:"username"` + Password string `json:"password"` + SystemToken string `json:"system_token"` } func (c Credentials) String() string { - return fmt.Sprintf("file: %s, username: %s, password: REDACTED", - c.Filename, c.Username) + return fmt.Sprintf("file: %s, username: %s, password: REDACTED, system_token: %s", + c.Filename, c.Username, c.SystemToken) } func systemCredentialsFile() string { @@ -83,10 +85,16 @@ } uMatch := userMatch.FindStringSubmatch(string(content)) pMatch := passMatch.FindStringSubmatch(string(content)) + tMatch := systemTokenMatch.FindStringSubmatch(string(content)) if len(uMatch) != 2 || len(pMatch) != 2 { return Credentials{}, ErrMalformedSccCredFile } - return Credentials{Username: uMatch[1], Password: pMatch[1]}, nil + token := "" + if len(tMatch) == 2 { + token = tMatch[1] + } + + return Credentials{Username: uMatch[1], Password: pMatch[1], SystemToken: token}, nil } func (c Credentials) write() error { @@ -103,23 +111,24 @@ } } buf := bytes.Buffer{} - fmt.Fprintf(&buf, "username=%s\npassword=%s\n", c.Username, c.Password) + fmt.Fprintf(&buf, "username=%s\npassword=%s\nsystem_token=%s\n", c.Username, c.Password, c.SystemToken) return os.WriteFile(path, buf.Bytes(), 0600) } // CreateCredentials writes credentials to path -func CreateCredentials(login, password, path string) error { +func CreateCredentials(login, password, systemToken, path string) error { c := Credentials{ - Filename: path, - Username: login, - Password: password, + Filename: path, + Username: login, + Password: password, + SystemToken: systemToken, } return c.write() } -func writeSystemCredentials(login, password string) error { +func writeSystemCredentials(login, password, systemToken string) error { path := systemCredentialsFile() - return CreateCredentials(login, password, path) + return CreateCredentials(login, password, systemToken, path) } func writeServiceCredentials(serviceName string) error { @@ -128,7 +137,7 @@ return err } path := serviceCredentialsFile(serviceName) - return CreateCredentials(c.Username, c.Password, path) + return CreateCredentials(c.Username, c.Password, c.SystemToken, path) } func removeSystemCredentials() error { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/credentials_test.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/credentials_test.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/credentials_test.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/credentials_test.go 2022-08-03 09:54:35.000000000 +0200 @@ -12,9 +12,9 @@ expectCreds Credentials expectErr error }{ - {"username=user1\npassword=pass1", Credentials{"", "user1", "pass1"}, nil}, - {" \n username = user1 \n password = pass1 \n", Credentials{"", "user1", "pass1"}, nil}, - {"username = user1 \n junk \n password = pass1 \n", Credentials{"", "user1", "pass1"}, nil}, + {"username=user1\npassword=pass1", Credentials{"", "user1", "pass1", ""}, nil}, + {" \n username = user1 \n password = pass1 \nsystem_token=\n", Credentials{"", "user1", "pass1", ""}, nil}, + {"username = user1 \n junk \n password = pass1 \nsystem_token=1234", Credentials{"", "user1", "pass1", "1234"}, nil}, {"USERNAME = user1 \n passed = pass1", Credentials{}, ErrMalformedSccCredFile}, {"username= \n password = \n", Credentials{}, ErrMalformedSccCredFile}, } @@ -33,14 +33,14 @@ if err != ErrMissingCredentialsFile { t.Fatalf("Expected [%s], got [%s]", ErrMissingCredentialsFile, err) } - if err := writeSystemCredentials("user1", "pass1"); err != nil { + if err := writeSystemCredentials("user1", "pass1", "1234"); err != nil { t.Fatalf("Unexpected error: %s", err) } c, err := getCredentials() if err != nil { t.Fatalf("Unexpected error: %s", err) } - if c.Username != "user1" || c.Password != "pass1" { + if c.Username != "user1" || c.Password != "pass1" || c.SystemToken != "1234" { t.Errorf("Unexpected user1 and pass1. Got: %s and %s", c.Username, c.Password) } @@ -55,10 +55,10 @@ func TestWriteCredentials(t *testing.T) { CFG.FsRoot = t.TempDir() - if err := writeSystemCredentials("user1", "pass1"); err != nil { + if err := writeSystemCredentials("user1", "pass1", "1234"); err != nil { t.Fatalf("Unexpected error: %s", err) } - expected := "username=user1\npassword=pass1\n" + expected := "username=user1\npassword=pass1\nsystem_token=1234\n" contents, _ := os.ReadFile(systemCredentialsFile()) got := string(contents) if got != expected { @@ -68,7 +68,7 @@ func TestWriteReadDeleteService(t *testing.T) { CFG.FsRoot = t.TempDir() - if err := writeSystemCredentials("user1", "pass1"); err != nil { + if err := writeSystemCredentials("user1", "pass1", "1234"); err != nil { t.Fatalf("Unexpected error: %s", err) } if err := writeServiceCredentials("service1"); err != nil { @@ -79,7 +79,7 @@ if err != nil { t.Fatalf("Unexpected error: %s", err) } - if rc.Username != "user1" || rc.Password != "pass1" { + if rc.Username != "user1" || rc.Password != "pass1" || rc.SystemToken != "1234" { t.Errorf("Got: %s and %s, expected user1 and pass1", rc.Username, rc.Password) } if err := removeServiceCredentials("service1"); err != nil { @@ -96,10 +96,10 @@ expectCreds Credentials expectErr error }{ - {"--proxy-user \"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%"}, nil}, - {"--proxy-user = \"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%"}, nil}, - {"proxy-user = \"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%"}, nil}, - {"proxy-user=\"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%"}, nil}, + {"--proxy-user \"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%", ""}, nil}, + {"--proxy-user = \"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%", ""}, nil}, + {"proxy-user = \"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%", ""}, nil}, + {"proxy-user=\"meuser1$:mepassord2%\"", Credentials{"", "meuser1$", "mepassord2%", ""}, nil}, {"", Credentials{}, ErrNoProxyCredentials}, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/errors.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/errors.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/errors.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/errors.go 2022-08-03 09:54:35.000000000 +0200 @@ -11,6 +11,7 @@ ErrMalformedSccCredFile = errors.New("Cannot parse credentials file") ErrMissingCredentialsFile = errors.New("Credentials file is missing") ErrSystemNotRegistered = errors.New("System not registered") + ErrPingFromUnregistered = errors.New("Keepalive ping not allowed from unregistered system.") ErrBaseProductDeactivation = errors.New("Unable to deactivate base product") ErrCannotDetectBaseProduct = errors.New("Unable to detect base product") ErrListExtensionsUnregistered = errors.New("System not registered") @@ -36,11 +37,12 @@ Commmand []string ExitCode int Output []byte + Err error } func (ze ZypperError) Error() string { - return fmt.Sprintf("command '%s' failed\nError: zypper returned %d with '%s'", - strings.Join(ze.Commmand, " "), ze.ExitCode, ze.Output) + return fmt.Sprintf("command '%s' failed\nError: zypper returned %d with '%s' (%s)", + strings.Join(ze.Commmand, " "), ze.ExitCode, ze.Output, ze.Err) } // APIError is returned on failed HTTP requests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/helpers_test.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/helpers_test.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/helpers_test.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/helpers_test.go 2022-08-03 09:54:35.000000000 +0200 @@ -24,7 +24,7 @@ password = "test" } CFG.FsRoot = t.TempDir() - err := writeSystemCredentials(username, password) + err := writeSystemCredentials(username, password, "") if err != nil { t.Fatal(err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/product.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/product.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/product.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/product.go 2022-08-03 09:54:35.000000000 +0200 @@ -26,7 +26,7 @@ Extensions []Product `json:"extensions,omitempty"` // these are used by YaST - ID int `json:"id"` + ID int `json:"-"` // handled by custom unmarshaller/marshaller Description string `xml:"description" json:"description,omitempty"` EULAURL string `json:"eula_url,omitempty"` FormerName string `json:"former_identifier,omitempty"` @@ -38,10 +38,11 @@ } // UnmarshalJSON custom unmarshaller for Product. -// Only SMT/RMT send the "available" field in their JSON responses. -// SCC does not, and the default Unmarshal() sets Available to the -// boolean zero-value which is false. This sets it to true instead. +// Special decoding is needed for the Available, IsBase and ID fields. func (p *Product) UnmarshalJSON(data []byte) error { + // Only SMT/RMT send the "available" field in their JSON responses. + // SCC does not, and the default Unmarshal() sets Available to the + // boolean zero-value which is false. This sets it to true instead. type product Product prod := product{ Available: true, @@ -49,6 +50,7 @@ if err := json.Unmarshal(data, &prod); err != nil { return err } + // migration paths contain is-base information as "base" attribute // while we default to "isbase" for YaST integration. // the rest of the SCC API uses `product_type="base"` instead. @@ -59,10 +61,50 @@ return err } prod.IsBase = prod.IsBase || mProd.Base || prod.ProductType == "base" + + // SCC and RMT servers send the ID field as an int. But SMT sends it + // as a string in the POST migrations call. This helper tries both. + prod.ID = findID(data) + *p = Product(prod) return nil } +// findID decodes the "id" field from data +func findID(data []byte) int { + // Try to decode as an int first. SCC/RMT case. + idInt := struct { + ID int `json:"id"` + }{} + if err := json.Unmarshal(data, &idInt); err == nil { + return idInt.ID + } + + // Decoding id as an int failed. Try to decode as a string. SMT case. + idStr := struct { + ID int `json:"id,string"` + }{} + if err := json.Unmarshal(data, &idStr); err == nil { + return idStr.ID + } + + return 0 +} + +// MarshalJSON is a custom JSON marshaller that includes the "id" field. +// This method is needed because the `json:"id"` tag can not be used +// on Product.ID because the that field requires a custom unmarshaller. +func (p *Product) MarshalJSON() ([]byte, error) { + type prodAlias Product + return json.Marshal(&struct { + ID int `json:"id"` + *prodAlias + }{ + ID: p.ID, + prodAlias: (*prodAlias)(p), + }) +} + // Edition returns VERSION[-RELEASE] for product func (p Product) Edition() string { if p.Release == "" { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/product_test.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/product_test.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/product_test.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/product_test.go 2022-08-03 09:54:35.000000000 +0200 @@ -129,3 +129,45 @@ t.Fatal("Expected error, got nil") } } + +func TestFindIDInt(t *testing.T) { + jsn := `{"id": 101361}` + var p Product + err := json.Unmarshal([]byte(jsn), &p) + if err != nil { + t.Fatalf("Error: %v", err) + } + if p.ID != 101361 { + t.Errorf("Expected: %d, got: %d", 101361, p.ID) + } +} + +func TestFindIDString(t *testing.T) { + jsn := `{"id": "101361"}` + var p Product + err := json.Unmarshal([]byte(jsn), &p) + if err != nil { + t.Fatalf("Error: %v", err) + } + if p.ID != 101361 { + t.Errorf("Expected: %d, got: %d", 101361, p.ID) + } +} + +func TestMarshallProductIntID(t *testing.T) { + p1 := Product{ID: 42} + jsn, err := json.Marshal(&p1) + if err != nil { + t.Fatalf("Error: %v", err) + } + + p2 := Product{} + err = json.Unmarshal([]byte(jsn), &p2) + if err != nil { + t.Fatalf("Error: %v", err) + } + + if p1.ID != p2.ID { + t.Errorf("Expected: %d, got: %d", p1.ID, p2.ID) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/internal/connect/zypper.go new/connect-ng-0.0.9~git5.75890b6/internal/connect/zypper.go --- old/connect-ng-0.0.8~git2.368ea44/internal/connect/zypper.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/internal/connect/zypper.go 2022-08-03 09:54:35.000000000 +0200 @@ -47,7 +47,7 @@ output, err := execute(cmd, validExitCodes) if err != nil { if ee, ok := err.(ExecuteError); ok { - return nil, ZypperError{Commmand: ee.Commmand, ExitCode: ee.ExitCode, Output: ee.Output} + return nil, ZypperError(ee) } } return output, nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/libsuseconnect/libsuseconnect.go new/connect-ng-0.0.9~git5.75890b6/libsuseconnect/libsuseconnect.go --- old/connect-ng-0.0.8~git2.368ea44/libsuseconnect/libsuseconnect.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/libsuseconnect/libsuseconnect.go 2022-08-03 09:54:35.000000000 +0200 @@ -68,7 +68,7 @@ var res struct { Credentials []string `json:"credentials"` } - res.Credentials = []string{login, password} + res.Credentials = []string{login, password, ""} jsn, _ := json.Marshal(&res) return C.CString(string(jsn)) } @@ -95,9 +95,9 @@ } //export create_credentials_file -func create_credentials_file(login, password, path *C.char) *C.char { +func create_credentials_file(login, password, token, path *C.char) *C.char { err := connect.CreateCredentials( - C.GoString(login), C.GoString(password), C.GoString(path)) + C.GoString(login), C.GoString(password), C.GoString(token), C.GoString(path)) if err != nil { return C.CString(errorToJSON(err)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/man/SUSEConnect.8 new/connect-ng-0.0.9~git5.75890b6/man/SUSEConnect.8 --- old/connect-ng-0.0.8~git2.368ea44/man/SUSEConnect.8 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/man/SUSEConnect.8 2022-08-03 09:54:35.000000000 +0200 @@ -71,6 +71,10 @@ \f[B]--status-text\f[R] Get current system registration status in text format. .TP +\f[B]--keepalive\f[R] +Send a keepalive call to the registration server, so it can detect which +systems are still running. +.TP \f[B]--write-config\f[R] Write options to config file at /etc/SUSEConnect. .TP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/man/SUSEConnect.8.md new/connect-ng-0.0.9~git5.75890b6/man/SUSEConnect.8.md --- old/connect-ng-0.0.8~git2.368ea44/man/SUSEConnect.8.md 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/man/SUSEConnect.8.md 2022-08-03 09:54:35.000000000 +0200 @@ -68,6 +68,10 @@ **--status-text** : Get current system registration status in text format. + **--keepalive** + : Send a keepalive call to the registration server, so it can detect which + systems are still running. + **--write-config** : Write options to config file at /etc/SUSEConnect. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/suseconnect/connectUsage.txt new/connect-ng-0.0.9~git5.75890b6/suseconnect/connectUsage.txt --- old/connect-ng-0.0.8~git2.368ea44/suseconnect/connectUsage.txt 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/suseconnect/connectUsage.txt 2022-08-03 09:54:35.000000000 +0200 @@ -35,6 +35,7 @@ format. --status-text Get current system registration status in text format. + --keepalive Sends data to SCC to update the system information. -l, --list-extensions List all extensions and modules available for installation on this system. --write-config Write options to config file at /etc/SUSEConnect. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/suseconnect/suseconnect.go new/connect-ng-0.0.9~git5.75890b6/suseconnect/suseconnect.go --- old/connect-ng-0.0.8~git2.368ea44/suseconnect/suseconnect.go 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/suseconnect/suseconnect.go 2022-08-03 09:54:35.000000000 +0200 @@ -35,6 +35,7 @@ func connectMain() { var ( status bool + keepAlive bool statusText bool debug bool writeConfig bool @@ -60,6 +61,7 @@ flag.BoolVar(&status, "status", false, "") flag.BoolVar(&status, "s", false, "") flag.BoolVar(&statusText, "status-text", false, "") + flag.BoolVar(&keepAlive, "keepalive", false, "") flag.BoolVar(&debug, "debug", false, "") flag.BoolVar(&writeConfig, "write-config", false, "") flag.BoolVar(&deRegister, "de-register", false, "") @@ -140,6 +142,9 @@ output, err := connect.GetProductStatuses("json") exitOnError(err) fmt.Println(output) + } else if keepAlive { + err := connect.SendKeepAlivePing() + exitOnError(err) } else if statusText { output, err := connect.GetProductStatuses("text") exitOnError(err) @@ -240,6 +245,10 @@ fmt.Print("Can not deregister base product. Use SUSEConnect -d to deactivate ") fmt.Print("the whole system.\n") os.Exit(70) + case connect.ErrPingFromUnregistered: + fmt.Print("Error sending keepalive: ") + fmt.Print("System is not registered. Use the --regcode parameter to register it.\n") + os.Exit(71) default: fmt.Printf("SUSEConnect error: %s\n", err) os.Exit(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/suseconnect-keepalive.service new/connect-ng-0.0.9~git5.75890b6/suseconnect-keepalive.service --- old/connect-ng-0.0.8~git2.368ea44/suseconnect-keepalive.service 1970-01-01 01:00:00.000000000 +0100 +++ new/connect-ng-0.0.9~git5.75890b6/suseconnect-keepalive.service 2022-08-03 09:54:35.000000000 +0200 @@ -0,0 +1,13 @@ +[Unit] +Description=Run SUSEConnect --keepalive +Wants=suseconnect-keepalive.timer + +[Service] +Type=oneshot +ExecStart=/usr/bin/SUSEConnect --keepalive +EnvironmentFile=-/etc/sysconfig/proxy + +# Filter out this special exit code, since it will be raised by `SUSEConnect +# --keepalive` whenever a system is not registered, which is a pretty typical +# scenario. +SuccessExitStatus=71 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/suseconnect-keepalive.timer new/connect-ng-0.0.9~git5.75890b6/suseconnect-keepalive.timer --- old/connect-ng-0.0.8~git2.368ea44/suseconnect-keepalive.timer 1970-01-01 01:00:00.000000000 +0100 +++ new/connect-ng-0.0.9~git5.75890b6/suseconnect-keepalive.timer 2022-08-03 09:54:35.000000000 +0200 @@ -0,0 +1,11 @@ +[Unit] +Description=Schedule daily SUSEConnect --keepalive calls +After=network-online.target + +[Timer] +# Run this timer every day at a randomized 24h delay. +OnCalendar=daily +RandomizedDelaySec=24h + +[Install] +WantedBy=timers.target diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/suseconnect-ng.spec new/connect-ng-0.0.9~git5.75890b6/suseconnect-ng.spec --- old/connect-ng-0.0.8~git2.368ea44/suseconnect-ng.spec 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/suseconnect-ng.spec 2022-08-03 09:54:35.000000000 +0200 @@ -30,7 +30,6 @@ Group: System/Management Source: connect-ng-%{version}.tar.xz Source1: %name-rpmlintrc -BuildRequires: git BuildRequires: golang-packaging BuildRequires: go >= 1.16 BuildRequires: zypper @@ -103,6 +102,8 @@ %prep %setup -q -n connect-ng-%{version} +# keep git metadata but don't use it for "VCS stamping" +mv .git .git.bak %build find %_builddir/.. @@ -130,10 +131,62 @@ install -D -m 644 %_builddir/go/src/%import_path/man/zypper-migration.8 %buildroot/%_mandir/man8/zypper-migration.8 install -D -m 644 %_builddir/go/src/%import_path/man/zypper-search-packages.8 %buildroot/%_mandir/man8/zypper-search-packages.8 +# Install the SUSEConnect --keepalive timer and service. +install -D -m 644 %_builddir/go/src/%import_path/suseconnect-keepalive.timer %buildroot/%_unitdir/suseconnect-keepalive.timer +install -D -m 644 %_builddir/go/src/%import_path/suseconnect-keepalive.service %buildroot/%_unitdir/suseconnect-keepalive.service +ln -sf service %buildroot/%_sbindir/rcsuseconnect-keepalive + find %_builddir/.. # we currently do not ship the source for any go module rm -rf %buildroot/usr/share/go +%pre +%service_add_pre suseconnect-keepalive.service suseconnect-keepalive.timer + +# in pre blocks the old version is still installed. This way we can detect +# if --keepalive was already present before +kainfo=0 +helptext=$(SUSEConnect --help) +if [ $? -eq 0 ]; then + echo "$helptext" | grep -q keepalive + kainfo=$? +fi + +if [ $kainfo -ne 0 ]; then + cat << EOF +Empowering you with enriched system visibility in the SUSE Customer Center + +SUSE is committed to helping provide better insights into the consumption of +SUSE subscriptions regardless of where they are running; physical or virtual, +on-prem or in the cloud. + +SUSE has been working on several improvements to the SUSE Customer Center (SCC), +RMT, and SUSE Manager to provide a clearer picture of your system landscape: + +- SUSE Manager v4.1+ now sends system information to SCC. +- SCC now captures which products are activated on systems that sit behind RMT + or SMT. +- This update will enable your system to "ping" SCC/RMT daily to + confirm the system's active status. This will help you identify or filter out + systems in SCC that are no longer running or decommissioned. As always, the + choice is yours, you can disable the daily ping by disabling the + suseconnect-keepalive systemd timer. + +We will continue improving our products to make it easier for you to view and +manage your subscription consumption. As always, we'd love to hear your feedback +about these improvements and any ideas you might have. +EOF +fi + +%post +%service_add_post suseconnect-keepalive.service suseconnect-keepalive.timer + +%preun +%service_del_preun suseconnect-keepalive.service suseconnect-keepalive.timer + +%postun +%service_del_postun suseconnect-keepalive.service suseconnect-keepalive.timer + %check %gotest -v %import_path/internal/connect %{?test_hwinfo_args} %gotest -v %import_path/suseconnect @@ -145,9 +198,12 @@ %_bindir/suseconnect %_bindir/SUSEConnect %_sbindir/SUSEConnect +%_sbindir/rcsuseconnect-keepalive /usr/lib/zypper/commands %_mandir/man8/* %_mandir/man5/* +%_unitdir/suseconnect-keepalive.service +%_unitdir/suseconnect-keepalive.timer %files -n libsuseconnect %license LICENSE LICENSE.LGPL diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/testdata/migrations-smt.json new/connect-ng-0.0.9~git5.75890b6/testdata/migrations-smt.json --- old/connect-ng-0.0.8~git2.368ea44/testdata/migrations-smt.json 1970-01-01 01:00:00.000000000 +0100 +++ new/connect-ng-0.0.9~git5.75890b6/testdata/migrations-smt.json 2022-08-03 09:54:35.000000000 +0200 @@ -0,0 +1,23 @@ +[ + [ + { + "product_type": "base", + "identifier": "suse-microos", + "release_stage": "released", + "free": true, + "productdataid": "2401", + "available": true, + "friendly_name": "SUSE Linux Enterprise Micro 5.2 x86_64", + "product_class": "MICROOS-X86", + "base": true, + "description": "SUSE Linux Enterprise Micro 5.2", + "shortname": "SUSE Linux Enterprise Micro", + "id": "101361", + "product_orig": "SUSE-MicroOS", + "release_type": null, + "cpe": "cpe:/o:suse:suse-microos:5.2", + "arch": "x86_64", + "version": "5.2" + } + ] +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/connect-ng-0.0.8~git2.368ea44/yast/lib/suse/toolkit/shim_utils.rb new/connect-ng-0.0.9~git5.75890b6/yast/lib/suse/toolkit/shim_utils.rb --- old/connect-ng-0.0.8~git2.368ea44/yast/lib/suse/toolkit/shim_utils.rb 2022-04-20 10:16:43.000000000 +0200 +++ new/connect-ng-0.0.9~git5.75890b6/yast/lib/suse/toolkit/shim_utils.rb 2022-08-03 09:54:35.000000000 +0200 @@ -1,3 +1,5 @@ +require 'openssl' + module SUSE module Toolkit # This module implements common boilerplate for wrapping libsuseconnect