diff --git a/1001-errtracker-neuter-error-tracker.patch b/1001-errtracker-neuter-error-tracker.patch deleted file mode 100644 index 9cf7a36..0000000 --- a/1001-errtracker-neuter-error-tracker.patch +++ /dev/null @@ -1,1241 +0,0 @@ -From 71c557b61cc29d0563e6fcf26aefc1365721a676 Mon Sep 17 00:00:00 2001 -From: Zygmunt Krynicki -Date: Wed, 6 Feb 2019 13:48:01 +0100 -Subject: [PATCH] errtracker: neuter error tracker - -The error report / tracker allows snapd to report various failures to -the store for central discovery. Unfortunately, the error tracker -depends on bson which is coming from the parts of mongodb package. - -With the mongo licensing issue and subsequent removal, to avoid FTBFS -while alternatives are considered, remove the error tracker -implementation to drop the dependency on bson. - -Signed-off-by: Zygmunt Krynicki ---- - errtracker/errtracker.go | 484 +----------------------------- - errtracker/errtracker_test.go | 544 ---------------------------------- - errtracker/export_test.go | 126 -------- - packaging/fedora/snapd.spec | 3 - - 4 files changed, 2 insertions(+), 1155 deletions(-) - delete mode 100644 errtracker/errtracker_test.go - delete mode 100644 errtracker/export_test.go - -diff --git a/errtracker/errtracker.go b/errtracker/errtracker.go -index d7507a9a3..8defc7594 100644 ---- a/errtracker/errtracker.go -+++ b/errtracker/errtracker.go -@@ -19,498 +19,18 @@ - - package errtracker - --import ( -- "bytes" -- "crypto/md5" -- "crypto/sha512" -- "fmt" -- "io" -- "io/ioutil" -- "net/http" -- "os" -- "os/exec" -- "path/filepath" -- "strings" -- "time" -- -- "github.com/snapcore/bolt" -- "gopkg.in/mgo.v2/bson" -- -- "github.com/snapcore/snapd/arch" -- "github.com/snapcore/snapd/dirs" -- "github.com/snapcore/snapd/httputil" -- "github.com/snapcore/snapd/logger" -- "github.com/snapcore/snapd/osutil" -- "github.com/snapcore/snapd/release" --) -- - var ( - CrashDbURLBase string - SnapdVersion string -- -- // The machine-id file is at different locations depending on how the system -- // is setup. On Fedora for example /var/lib/dbus/machine-id doesn't exist -- // but we have /etc/machine-id. See -- // https://www.freedesktop.org/software/systemd/man/machine-id.html for a -- // few more details. -- machineIDs = []string{"/etc/machine-id", "/var/lib/dbus/machine-id"} -- -- mockedHostSnapd = "" -- mockedCoreSnapd = "" -- -- snapConfineProfile = "/etc/apparmor.d/usr.lib.snapd.snap-confine" -- -- procCpuinfo = "/proc/cpuinfo" -- procSelfExe = "/proc/self/exe" -- procSelfCwd = "/proc/self/cwd" -- procSelfCmdline = "/proc/self/cmdline" -- -- osGetenv = os.Getenv -- timeNow = time.Now - ) - --type reportsDB struct { -- db *bolt.DB -- -- // map of hash(dupsig) -> time-of-report -- reportedBucket *bolt.Bucket -- -- // time until an error report is cleaned from the database, -- // usually 7 days -- cleanupTime time.Duration --} -- --func hashString(s string) string { -- h := sha512.New() -- io.WriteString(h, s) -- return fmt.Sprintf("%x", h.Sum(nil)) --} -- --func newReportsDB(fname string) (*reportsDB, error) { -- if err := os.MkdirAll(filepath.Dir(fname), 0755); err != nil { -- return nil, err -- } -- bdb, err := bolt.Open(fname, 0600, &bolt.Options{ -- Timeout: 10 * time.Second, -- }) -- if err != nil { -- return nil, err -- } -- bdb.Update(func(tx *bolt.Tx) error { -- _, err := tx.CreateBucketIfNotExists([]byte("reported")) -- if err != nil { -- return fmt.Errorf("create bucket: %s", err) -- } -- return nil -- }) -- -- db := &reportsDB{ -- db: bdb, -- cleanupTime: time.Duration(7 * 24 * time.Hour), -- } -- -- return db, nil --} -- --func (db *reportsDB) Close() error { -- return db.db.Close() --} -- --// AlreadyReported returns true if an identical report has been sent recently --func (db *reportsDB) AlreadyReported(dupSig string) bool { -- // robustness -- if db == nil { -- return false -- } -- var reported []byte -- db.db.View(func(tx *bolt.Tx) error { -- b := tx.Bucket([]byte("reported")) -- reported = b.Get([]byte(hashString(dupSig))) -- return nil -- }) -- return len(reported) > 0 --} -- --func (db *reportsDB) cleanupOldRecords() { -- db.db.Update(func(tx *bolt.Tx) error { -- now := time.Now() -- -- b := tx.Bucket([]byte("reported")) -- b.ForEach(func(dupSigHash, reportTime []byte) error { -- var t time.Time -- t.UnmarshalBinary(reportTime) -- -- if now.After(t.Add(db.cleanupTime)) { -- if err := b.Delete(dupSigHash); err != nil { -- return err -- } -- } -- return nil -- }) -- return nil -- }) --} -- --// MarkReported marks an error report as reported to the error tracker --func (db *reportsDB) MarkReported(dupSig string) error { -- // robustness -- if db == nil { -- return fmt.Errorf("cannot mark error report as reported with an uninitialized reports database") -- } -- db.cleanupOldRecords() -- -- return db.db.Update(func(tx *bolt.Tx) error { -- b := tx.Bucket([]byte("reported")) -- tb, err := time.Now().MarshalBinary() -- if err != nil { -- return err -- } -- return b.Put([]byte(hashString(dupSig)), tb) -- }) --} -- --func whoopsieEnabled() bool { -- cmd := exec.Command("systemctl", "is-enabled", "whoopsie.service") -- output, _ := cmd.CombinedOutput() -- switch string(output) { -- case "enabled\n": -- return true -- case "disabled\n": -- return false -- default: -- logger.Debugf("unexpected output when checking for whoopsie.service (not installed?): %s", output) -- return true -- } --} -- --// distroRelease returns a distro release as it is expected by daisy.ubuntu.com --func distroRelease() string { -- ID := release.ReleaseInfo.ID -- if ID == "ubuntu" { -- ID = "Ubuntu" -- } -- -- return fmt.Sprintf("%s %s", ID, release.ReleaseInfo.VersionID) --} -- --func readMachineID() ([]byte, error) { -- for _, id := range machineIDs { -- machineID, err := ioutil.ReadFile(id) -- if err == nil { -- return bytes.TrimSpace(machineID), nil -- } else if !os.IsNotExist(err) { -- logger.Noticef("cannot read %s: %s", id, err) -- } -- } -- -- return nil, fmt.Errorf("cannot report: no suitable machine id file found") --} -- --func snapConfineProfileDigest(suffix string) string { -- profileText, err := ioutil.ReadFile(filepath.Join(dirs.GlobalRootDir, snapConfineProfile+suffix)) -- if err != nil { -- return "" -- } -- // NOTE: uses md5sum for easier comparison against dpkg meta-data -- return fmt.Sprintf("%x", md5.Sum(profileText)) --} -- --var didSnapdReExec = func() string { -- // TODO: move this into osutil.Reexeced() ? -- exe, err := os.Readlink(procSelfExe) -- if err != nil { -- return "unknown" -- } -- if strings.HasPrefix(exe, dirs.SnapMountDir) { -- return "yes" -- } -- return "no" --} -- - // Report reports an error with the given snap to the error tracker - func Report(snap, errMsg, dupSig string, extra map[string]string) (string, error) { -- if extra == nil { -- extra = make(map[string]string) -- } -- extra["ProblemType"] = "Snap" -- extra["Snap"] = snap -- -- // check if we haven't already reported this error -- db, err := newReportsDB(dirs.ErrtrackerDbDir) -- if err != nil { -- logger.Noticef("cannot open error reports database: %v", err) -- } -- defer db.Close() -- -- if db.AlreadyReported(dupSig) { -- return "already-reported", nil -- } -- -- // do the actual report -- oopsID, err := report(errMsg, dupSig, extra) -- if err != nil { -- return "", err -- } -- if err := db.MarkReported(dupSig); err != nil { -- logger.Noticef("cannot mark %s as reported: %s", oopsID, err) -- } -- -- return oopsID, nil -+ return "", nil - } - - // ReportRepair reports an error with the given repair assertion script - // to the error tracker - func ReportRepair(repair, errMsg, dupSig string, extra map[string]string) (string, error) { -- if extra == nil { -- extra = make(map[string]string) -- } -- extra["ProblemType"] = "Repair" -- extra["Repair"] = repair -- -- return report(errMsg, dupSig, extra) --} -- --func detectVirt() string { -- cmd := exec.Command("systemd-detect-virt") -- output, err := cmd.CombinedOutput() -- if err != nil { -- return "" -- } -- return strings.TrimSpace(string(output)) --} -- --func journalError() string { -- // TODO: look into using systemd package (needs refactor) -- -- // Before changing this line to be more consistent or nicer or anything -- // else, remember it needs to run a lot of different systemd's: today, -- // anything from 238 (on arch) to 204 (on ubuntu 14.04); this is why -- // doing the refactor to the systemd package to only worry about this in -- // there might be worth it. -- output, err := exec.Command("journalctl", "-b", "--priority=warning..err", "--lines=1000").CombinedOutput() -- if err != nil { -- if len(output) == 0 { -- return fmt.Sprintf("error: %v", err) -- } -- output = append(output, fmt.Sprintf("\nerror: %v", err)...) -- } -- return string(output) --} -- --func procCpuinfoMinimal() string { -- buf, err := ioutil.ReadFile(procCpuinfo) -- if err != nil { -- // if we can't read cpuinfo, we want to know _why_ -- return fmt.Sprintf("error: %v", err) -- } -- idx := bytes.LastIndex(buf, []byte("\nprocessor\t:")) -- -- // if not found (which will happen on non-x86 architectures, which is ok -- // because they'd typically not have the same info over and over again), -- // return whole buffer; otherwise, return from just after the \n -- return string(buf[idx+1:]) --} -- --func procExe() string { -- out, err := os.Readlink(procSelfExe) -- if err != nil { -- return fmt.Sprintf("error: %v", err) -- } -- return out --} -- --func procCwd() string { -- out, err := os.Readlink(procSelfCwd) -- if err != nil { -- return fmt.Sprintf("error: %v", err) -- } -- return out --} -- --func procCmdline() string { -- out, err := ioutil.ReadFile(procSelfCmdline) -- if err != nil { -- return fmt.Sprintf("error: %v", err) -- } -- return string(out) --} -- --func environ() string { -- safeVars := []string{ -- "SHELL", "TERM", "LANGUAGE", "LANG", "LC_CTYPE", -- "LC_COLLATE", "LC_TIME", "LC_NUMERIC", -- "LC_MONETARY", "LC_MESSAGES", "LC_PAPER", -- "LC_NAME", "LC_ADDRESS", "LC_TELEPHONE", -- "LC_MEASUREMENT", "LC_IDENTIFICATION", "LOCPATH", -- } -- unsafeVars := []string{"XDG_RUNTIME_DIR", "LD_PRELOAD", "LD_LIBRARY_PATH"} -- knownPaths := map[string]bool{ -- "/snap/bin": true, -- "/var/lib/snapd/snap/bin": true, -- "/sbin": true, -- "/bin": true, -- "/usr/sbin": true, -- "/usr/bin": true, -- "/usr/local/sbin": true, -- "/usr/local/bin": true, -- "/usr/local/games": true, -- "/usr/games": true, -- } -- -- // + 1 for PATH -- out := make([]string, 0, len(safeVars)+len(unsafeVars)+1) -- -- for _, k := range safeVars { -- if v := osGetenv(k); v != "" { -- out = append(out, fmt.Sprintf("%s=%s", k, v)) -- } -- } -- -- for _, k := range unsafeVars { -- if v := osGetenv(k); v != "" { -- out = append(out, k+"=") -- } -- } -- -- if paths := filepath.SplitList(osGetenv("PATH")); len(paths) > 0 { -- for i, p := range paths { -- p = filepath.Clean(p) -- if !knownPaths[p] { -- if strings.Contains(p, "/home") || strings.Contains(p, "/tmp") { -- p = "(user)" -- } else { -- p = "(custom)" -- } -- } -- paths[i] = p -- } -- out = append(out, fmt.Sprintf("PATH=%s", strings.Join(paths, string(filepath.ListSeparator)))) -- } -- -- return strings.Join(out, "\n") --} -- --func report(errMsg, dupSig string, extra map[string]string) (string, error) { -- if CrashDbURLBase == "" { -- return "", nil -- } -- if extra == nil || extra["ProblemType"] == "" { -- return "", fmt.Errorf(`key "ProblemType" not set in %v`, extra) -- } -- -- if !whoopsieEnabled() { -- return "", nil -- } -- -- machineID, err := readMachineID() -- if err != nil { -- return "", err -- } -- -- identifier := fmt.Sprintf("%x", sha512.Sum512(machineID)) -- -- crashDbUrl := fmt.Sprintf("%s/%s", CrashDbURLBase, identifier) -- -- hostSnapdPath := filepath.Join(dirs.DistroLibExecDir, "snapd") -- coreSnapdPath := filepath.Join(dirs.SnapMountDir, "core/current/usr/lib/snapd/snapd") -- if mockedHostSnapd != "" { -- hostSnapdPath = mockedHostSnapd -- } -- if mockedCoreSnapd != "" { -- coreSnapdPath = mockedCoreSnapd -- } -- hostBuildID, _ := osutil.ReadBuildID(hostSnapdPath) -- coreBuildID, _ := osutil.ReadBuildID(coreSnapdPath) -- if hostBuildID == "" { -- hostBuildID = "unknown" -- } -- if coreBuildID == "" { -- coreBuildID = "unknown" -- } -- -- report := map[string]string{ -- "Architecture": arch.UbuntuArchitecture(), -- "SnapdVersion": SnapdVersion, -- "DistroRelease": distroRelease(), -- "HostSnapdBuildID": hostBuildID, -- "CoreSnapdBuildID": coreBuildID, -- "Date": timeNow().Format(time.ANSIC), -- "KernelVersion": osutil.KernelVersion(), -- "ErrorMessage": errMsg, -- "DuplicateSignature": dupSig, -- -- "JournalError": journalError(), -- "ExecutablePath": procExe(), -- "ProcCmdline": procCmdline(), -- "ProcCpuinfoMinimal": procCpuinfoMinimal(), -- "ProcCwd": procCwd(), -- "ProcEnviron": environ(), -- "DetectedVirt": detectVirt(), -- "SourcePackage": "snapd", -- -- "DidSnapdReExec": didSnapdReExec(), -- } -- -- if desktop := osGetenv("XDG_CURRENT_DESKTOP"); desktop != "" { -- report["CurrentDesktop"] = desktop -- } -- -- for k, v := range extra { -- // only set if empty -- if _, ok := report[k]; !ok { -- report[k] = v -- } -- } -- -- // include md5 hashes of the apparmor conffile for easier debbuging -- // of not-updated snap-confine apparmor profiles -- for _, sp := range []struct { -- suffix string -- key string -- }{ -- {"", "MD5SumSnapConfineAppArmorProfile"}, -- {".dpkg-new", "MD5SumSnapConfineAppArmorProfileDpkgNew"}, -- {".real", "MD5SumSnapConfineAppArmorProfileReal"}, -- {".real.dpkg-new", "MD5SumSnapConfineAppArmorProfileRealDpkgNew"}, -- } { -- digest := snapConfineProfileDigest(sp.suffix) -- if digest != "" { -- report[sp.key] = digest -- } -- -- } -- -- // see if we run in testing mode -- if osutil.GetenvBool("SNAPPY_TESTING") { -- logger.Noticef("errtracker.Report is *not* sent because SNAPPY_TESTING is set") -- logger.Noticef("report: %v", report) -- return "oops-not-sent", nil -- } -- -- // send it for real -- reportBson, err := bson.Marshal(report) -- if err != nil { -- return "", err -- } -- client := &http.Client{} -- req, err := http.NewRequest("POST", crashDbUrl, bytes.NewBuffer(reportBson)) -- if err != nil { -- return "", err -- } -- req.Header.Add("Content-Type", "application/octet-stream") -- req.Header.Add("X-Whoopsie-Version", httputil.UserAgent()) -- resp, err := client.Do(req) -- if err != nil { -- return "", err -- } -- defer resp.Body.Close() -- if resp.StatusCode != 200 { -- return "", fmt.Errorf("cannot upload error report, return code: %d", resp.StatusCode) -- } -- oopsID, err := ioutil.ReadAll(resp.Body) -- if err != nil { -- return "", err -- } -- -- return string(oopsID), nil -+ return "", nil - } -diff --git a/errtracker/errtracker_test.go b/errtracker/errtracker_test.go -deleted file mode 100644 -index a79535618..000000000 ---- a/errtracker/errtracker_test.go -+++ /dev/null -@@ -1,544 +0,0 @@ --// -*- Mode: Go; indent-tabs-mode: t -*- -- --/* -- * Copyright (C) 2017 Canonical Ltd -- * -- * This program is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 3 as -- * published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program. If not, see . -- * -- */ -- --package errtracker_test -- --import ( -- "crypto/sha512" -- "fmt" -- "io/ioutil" -- "net/http" -- "net/http/httptest" -- "os" -- "path/filepath" -- "sort" -- "strings" -- "testing" -- "time" -- -- "gopkg.in/mgo.v2/bson" -- -- . "gopkg.in/check.v1" -- -- "github.com/snapcore/snapd/arch" -- "github.com/snapcore/snapd/dirs" -- "github.com/snapcore/snapd/errtracker" -- "github.com/snapcore/snapd/osutil" -- "github.com/snapcore/snapd/release" -- "github.com/snapcore/snapd/testutil" --) -- --// Hook up check.v1 into the "go test" runner --func Test(t *testing.T) { TestingT(t) } -- --type ErrtrackerTestSuite struct { -- testutil.BaseTest -- -- tmpdir string -- -- hostBuildID string -- coreBuildID string -- distroRelease string --} -- --var _ = Suite(&ErrtrackerTestSuite{}) -- --var truePath = osutil.LookPathDefault("true", "/bin/true") --var falsePath = osutil.LookPathDefault("false", "/bin/false") -- --const someJournalEntry = "Mar 29 22:08:00 localhost kernel: [81B blob data]" -- --func (s *ErrtrackerTestSuite) SetUpTest(c *C) { -- s.BaseTest.SetUpTest(c) -- -- s.tmpdir = c.MkDir() -- dirs.SetRootDir(s.tmpdir) -- -- p := filepath.Join(s.tmpdir, "machine-id") -- err := ioutil.WriteFile(p, []byte("bbb1a6a5bcdb418380056a2d759c3f7c"), 0644) -- c.Assert(err, IsNil) -- s.AddCleanup(errtracker.MockMachineIDPaths([]string{p})) -- s.AddCleanup(errtracker.MockHostSnapd(truePath)) -- s.AddCleanup(errtracker.MockCoreSnapd(falsePath)) -- s.AddCleanup(errtracker.MockReExec(func() string { -- return "yes" -- })) -- mockDetectVirt := testutil.MockCommand(c, "systemd-detect-virt", "echo none") -- s.AddCleanup(mockDetectVirt.Restore) -- -- s.hostBuildID, err = osutil.ReadBuildID(truePath) -- c.Assert(err, IsNil) -- s.coreBuildID, err = osutil.ReadBuildID(falsePath) -- c.Assert(err, IsNil) -- if release.ReleaseInfo.ID == "ubuntu" { -- s.distroRelease = fmt.Sprintf("%s %s", strings.Title(release.ReleaseInfo.ID), release.ReleaseInfo.VersionID) -- } else { -- s.distroRelease = fmt.Sprintf("%s %s", release.ReleaseInfo.ID, release.ReleaseInfo.VersionID) -- } -- -- mockCpuinfo := filepath.Join(s.tmpdir, "cpuinfo") -- mockSelfCmdline := filepath.Join(s.tmpdir, "self.cmdline") -- mockSelfExe := filepath.Join(s.tmpdir, "self.exe") -- mockSelfCwd := filepath.Join(s.tmpdir, "self.cwd") -- -- c.Assert(ioutil.WriteFile(mockCpuinfo, []byte(` --processor : 0 --bugs : very yes --etc : ... -- --processor : 42 --bugs : very yes --`[1:]), 0644), IsNil) -- c.Assert(ioutil.WriteFile(mockSelfCmdline, []byte("foo\x00bar\x00baz"), 0644), IsNil) -- c.Assert(os.Symlink("target of /proc/self/exe", mockSelfExe), IsNil) -- c.Assert(os.Symlink("target of /proc/self/cwd", mockSelfCwd), IsNil) -- -- s.AddCleanup(errtracker.MockOsGetenv(func(s string) string { -- switch s { -- case "SHELL": -- return "/bin/sh" -- case "XDG_CURRENT_DESKTOP": -- return "Unity" -- } -- return "" -- })) -- s.AddCleanup(errtracker.MockProcCpuinfo(mockCpuinfo)) -- s.AddCleanup(errtracker.MockProcSelfCmdline(mockSelfCmdline)) -- s.AddCleanup(errtracker.MockProcSelfExe(mockSelfExe)) -- s.AddCleanup(errtracker.MockProcSelfCwd(mockSelfCwd)) -- s.AddCleanup(testutil.MockCommand(c, "journalctl", "echo "+someJournalEntry).Restore) --} -- --func (s *ErrtrackerTestSuite) TestReport(c *C) { -- n := 0 -- identifier := "" -- -- snapConfineProfile := filepath.Join(s.tmpdir, "/etc/apparmor.d/usr.lib.snapd.snap-confine") -- err := os.MkdirAll(filepath.Dir(snapConfineProfile), 0755) -- c.Assert(err, IsNil) -- err = ioutil.WriteFile(snapConfineProfile, []byte("# fake profile of snap-confine"), 0644) -- c.Assert(err, IsNil) -- -- err = ioutil.WriteFile(snapConfineProfile+".dpkg-new", []byte{0}, 0644) -- c.Assert(err, IsNil) -- err = ioutil.WriteFile(snapConfineProfile+".real", []byte{0}, 0644) -- c.Assert(err, IsNil) -- err = ioutil.WriteFile(snapConfineProfile+".real.dpkg-new", []byte{0}, 0644) -- c.Assert(err, IsNil) -- -- prev := errtracker.SnapdVersion -- defer func() { errtracker.SnapdVersion = prev }() -- errtracker.SnapdVersion = "some-snapd-version" -- -- handler := func(w http.ResponseWriter, r *http.Request) { -- switch n { -- case 0: -- c.Check(r.Method, Equals, "POST") -- c.Check(r.URL.Path, Matches, "/[a-z0-9]+") -- identifier = r.URL.Path -- b, err := ioutil.ReadAll(r.Body) -- c.Assert(err, IsNil) -- -- var data map[string]string -- err = bson.Unmarshal(b, &data) -- c.Assert(err, IsNil) -- c.Check(data, DeepEquals, map[string]string{ -- "DistroRelease": s.distroRelease, -- "HostSnapdBuildID": s.hostBuildID, -- "CoreSnapdBuildID": s.coreBuildID, -- "SnapdVersion": "some-snapd-version", -- "Date": "Fri Feb 17 09:51:00 2017", -- "KernelVersion": osutil.KernelVersion(), -- "ErrorMessage": "failed to do stuff", -- "DuplicateSignature": "[failed to do stuff]", -- "Architecture": arch.UbuntuArchitecture(), -- "DidSnapdReExec": "yes", -- -- "ProblemType": "Snap", -- "Snap": "some-snap", -- "Channel": "beta", -- -- "ProcCpuinfoMinimal": "processor\t: 42\nbugs\t\t: very yes\n", -- "ExecutablePath": "target of /proc/self/exe", -- "ProcCwd": "target of /proc/self/cwd", -- "ProcCmdline": "foo\x00bar\x00baz", -- "ProcEnviron": "SHELL=/bin/sh", -- "JournalError": someJournalEntry + "\n", -- "SourcePackage": "snapd", -- "CurrentDesktop": "Unity", -- "DetectedVirt": "none", -- -- "MD5SumSnapConfineAppArmorProfile": "7a7aa5f21063170c1991b84eb8d86de1", -- "MD5SumSnapConfineAppArmorProfileDpkgNew": "93b885adfe0da089cdf634904fd59f71", -- "MD5SumSnapConfineAppArmorProfileReal": "93b885adfe0da089cdf634904fd59f71", -- "MD5SumSnapConfineAppArmorProfileRealDpkgNew": "93b885adfe0da089cdf634904fd59f71", -- }) -- fmt.Fprintf(w, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID") -- case 1: -- c.Check(r.Method, Equals, "POST") -- c.Check(r.URL.Path, Matches, identifier) -- fmt.Fprintf(w, "xxxxx-f78d-11e6-8df0-fa163eaf9b83 OOPSID") -- default: -- c.Fatalf("expected one request, got %d", n+1) -- } -- -- n++ -- } -- -- server := httptest.NewServer(http.HandlerFunc(handler)) -- defer server.Close() -- restorer := errtracker.MockCrashDbURL(server.URL) -- defer restorer() -- restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) }) -- defer restorer() -- -- id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{ -- "Channel": "beta", -- }) -- c.Check(err, IsNil) -- c.Check(id, Equals, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID") -- c.Check(n, Equals, 1) -- -- // run again with the *same* dupSig and verify that it won't send -- // that again -- id, err = errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{ -- "Channel": "beta", -- }) -- c.Check(err, IsNil) -- c.Check(id, Equals, "already-reported") -- c.Check(n, Equals, 1) -- -- // run again with different data, verify identifier is unchanged -- id, err = errtracker.Report("some-other-snap", "failed to do more stuff", "[failed to do more stuff]", nil) -- c.Check(err, IsNil) -- c.Check(id, Equals, "xxxxx-f78d-11e6-8df0-fa163eaf9b83 OOPSID") -- c.Check(n, Equals, 2) --} -- --func (s *ErrtrackerTestSuite) TestReportUnderTesting(c *C) { -- os.Setenv("SNAPPY_TESTING", "1") -- defer os.Unsetenv("SNAPPY_TESTING") -- -- n := 0 -- prev := errtracker.SnapdVersion -- defer func() { errtracker.SnapdVersion = prev }() -- errtracker.SnapdVersion = "some-snapd-version" -- -- handler := func(w http.ResponseWriter, r *http.Request) { -- n++ -- } -- -- server := httptest.NewServer(http.HandlerFunc(handler)) -- defer server.Close() -- restorer := errtracker.MockCrashDbURL(server.URL) -- defer restorer() -- restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) }) -- defer restorer() -- -- id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{ -- "Channel": "beta", -- }) -- c.Check(err, IsNil) -- c.Check(id, Equals, "oops-not-sent") -- c.Check(n, Equals, 0) --} -- --func (s *ErrtrackerTestSuite) TestTriesAllKnownMachineIDs(c *C) { -- p := filepath.Join(c.MkDir(), "machine-id") -- machineID := []byte("bbb1a6a5bcdb418380056a2d759c3f7c") -- err := ioutil.WriteFile(p, machineID, 0644) -- c.Assert(err, IsNil) -- s.AddCleanup(errtracker.MockMachineIDPaths([]string{"/does/not/exist", p})) -- -- n := 0 -- var identifiers []string -- handler := func(w http.ResponseWriter, r *http.Request) { -- identifiers = append(identifiers, r.URL.Path) -- n++ -- } -- -- server := httptest.NewServer(http.HandlerFunc(handler)) -- defer server.Close() -- restorer := errtracker.MockCrashDbURL(server.URL) -- defer restorer() -- restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) }) -- defer restorer() -- -- _, err = errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{ -- "Channel": "beta", -- }) -- c.Check(err, IsNil) -- c.Check(n, Equals, 1) -- c.Check(identifiers, DeepEquals, []string{fmt.Sprintf("/%x", sha512.Sum512(machineID))}) --} -- --func (s *ErrtrackerTestSuite) TestReportRepair(c *C) { -- n := 0 -- prev := errtracker.SnapdVersion -- defer func() { errtracker.SnapdVersion = prev }() -- errtracker.SnapdVersion = "some-snapd-version" -- -- handler := func(w http.ResponseWriter, r *http.Request) { -- switch n { -- case 0: -- c.Check(r.Method, Equals, "POST") -- c.Check(r.URL.Path, Matches, "/[a-z0-9]+") -- b, err := ioutil.ReadAll(r.Body) -- c.Assert(err, IsNil) -- -- var data map[string]string -- err = bson.Unmarshal(b, &data) -- c.Assert(err, IsNil) -- c.Check(data, DeepEquals, map[string]string{ -- "DistroRelease": s.distroRelease, -- "HostSnapdBuildID": s.hostBuildID, -- "CoreSnapdBuildID": s.coreBuildID, -- "SnapdVersion": "some-snapd-version", -- "Date": "Fri Feb 17 09:51:00 2017", -- "KernelVersion": osutil.KernelVersion(), -- "Architecture": arch.UbuntuArchitecture(), -- "DidSnapdReExec": "yes", -- -- "ProblemType": "Repair", -- "Repair": `"repair (1; brand-id:canonical)"`, -- "ErrorMessage": "failure in script", -- "DuplicateSignature": "[dupSig]", -- "BrandID": "canonical", -- -- "ProcCpuinfoMinimal": "processor\t: 42\nbugs\t\t: very yes\n", -- "ExecutablePath": "target of /proc/self/exe", -- "ProcCwd": "target of /proc/self/cwd", -- "ProcCmdline": "foo\x00bar\x00baz", -- "ProcEnviron": "SHELL=/bin/sh", -- "JournalError": someJournalEntry + "\n", -- "SourcePackage": "snapd", -- "CurrentDesktop": "Unity", -- "DetectedVirt": "none", -- }) -- fmt.Fprintf(w, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID") -- default: -- c.Fatalf("expected one request, got %d", n+1) -- } -- -- n++ -- } -- -- server := httptest.NewServer(http.HandlerFunc(handler)) -- defer server.Close() -- restorer := errtracker.MockCrashDbURL(server.URL) -- defer restorer() -- restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) }) -- defer restorer() -- -- id, err := errtracker.ReportRepair(`"repair (1; brand-id:canonical)"`, "failure in script", "[dupSig]", map[string]string{ -- "BrandID": "canonical", -- }) -- c.Check(err, IsNil) -- c.Check(id, Equals, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID") -- c.Check(n, Equals, 1) --} -- --func (s *ErrtrackerTestSuite) TestReportWithWhoopsieDisabled(c *C) { -- mockCmd := testutil.MockCommand(c, "systemctl", "echo disabled; exit 1") -- defer mockCmd.Restore() -- -- handler := func(w http.ResponseWriter, r *http.Request) { -- c.Fatalf("The server should not be hit from here") -- } -- server := httptest.NewServer(http.HandlerFunc(handler)) -- defer server.Close() -- restorer := errtracker.MockCrashDbURL(server.URL) -- defer restorer() -- -- id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", nil) -- c.Check(err, IsNil) -- c.Check(id, Equals, "") --} -- --func (s *ErrtrackerTestSuite) TestReportWithNoWhoopsieInstalled(c *C) { -- mockCmd := testutil.MockCommand(c, "systemctl", "echo Failed to get unit file state for whoopsie.service; exit 1") -- defer mockCmd.Restore() -- -- n := 0 -- handler := func(w http.ResponseWriter, r *http.Request) { -- fmt.Fprintf(w, "1234-oopsid") -- n++ -- } -- server := httptest.NewServer(http.HandlerFunc(handler)) -- defer server.Close() -- restorer := errtracker.MockCrashDbURL(server.URL) -- defer restorer() -- -- id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", nil) -- c.Check(err, IsNil) -- c.Check(id, Equals, "1234-oopsid") -- c.Check(n, Equals, 1) --} -- --func (s *ErrtrackerTestSuite) TestProcCpuinfo(c *C) { -- fn := filepath.Join(s.tmpdir, "cpuinfo") -- // sanity check -- buf, err := ioutil.ReadFile(fn) -- c.Assert(err, IsNil) -- c.Check(string(buf), Equals, ` --processor : 0 --bugs : very yes --etc : ... -- --processor : 42 --bugs : very yes --`[1:]) -- -- // just the last processor entry -- c.Check(errtracker.ProcCpuinfoMinimal(), Equals, ` --processor : 42 --bugs : very yes --`[1:]) -- -- // if no processor line, just return the whole thing -- c.Assert(ioutil.WriteFile(fn, []byte("yadda yadda\n"), 0644), IsNil) -- c.Check(errtracker.ProcCpuinfoMinimal(), Equals, "yadda yadda\n") -- -- c.Assert(os.Remove(fn), IsNil) -- c.Check(errtracker.ProcCpuinfoMinimal(), Matches, "error: .* no such file or directory") --} -- --func (s *ErrtrackerTestSuite) TestProcExe(c *C) { -- c.Check(errtracker.ProcExe(), Equals, "target of /proc/self/exe") -- c.Assert(os.Remove(filepath.Join(s.tmpdir, "self.exe")), IsNil) -- c.Check(errtracker.ProcExe(), Matches, "error: .* no such file or directory") --} -- --func (s *ErrtrackerTestSuite) TestProcCwd(c *C) { -- c.Check(errtracker.ProcCwd(), Equals, "target of /proc/self/cwd") -- c.Assert(os.Remove(filepath.Join(s.tmpdir, "self.cwd")), IsNil) -- c.Check(errtracker.ProcCwd(), Matches, "error: .* no such file or directory") --} -- --func (s *ErrtrackerTestSuite) TestProcCmdline(c *C) { -- c.Check(errtracker.ProcCmdline(), Equals, "foo\x00bar\x00baz") -- c.Assert(os.Remove(filepath.Join(s.tmpdir, "self.cmdline")), IsNil) -- c.Check(errtracker.ProcCmdline(), Matches, "error: .* no such file or directory") --} -- --func (s *ErrtrackerTestSuite) TestJournalError(c *C) { -- jctl := testutil.MockCommand(c, "journalctl", "echo "+someJournalEntry) -- defer jctl.Restore() -- c.Check(errtracker.JournalError(), Equals, someJournalEntry+"\n") -- c.Check(jctl.Calls(), DeepEquals, [][]string{ -- {"journalctl", "-b", "--priority=warning..err", "--lines=1000"}, -- }) --} -- --func (s *ErrtrackerTestSuite) TestJournalErrorSilentError(c *C) { -- jctl := testutil.MockCommand(c, "journalctl", "kill $$") -- defer jctl.Restore() -- c.Check(errtracker.JournalError(), Matches, "error: signal: [Tt]erminated") -- c.Check(jctl.Calls(), DeepEquals, [][]string{ -- {"journalctl", "-b", "--priority=warning..err", "--lines=1000"}, -- }) --} -- --func (s *ErrtrackerTestSuite) TestJournalErrorError(c *C) { -- jctl := testutil.MockCommand(c, "journalctl", "echo OOPS; exit 1") -- defer jctl.Restore() -- c.Check(errtracker.JournalError(), Equals, "OOPS\n\nerror: exit status 1") -- c.Check(jctl.Calls(), DeepEquals, [][]string{ -- {"journalctl", "-b", "--priority=warning..err", "--lines=1000"}, -- }) --} -- --func (s *ErrtrackerTestSuite) TestEnviron(c *C) { -- defer errtracker.MockOsGetenv(func(s string) string { -- switch s { -- case "SHELL": -- // marked as safe -- return "/bin/sh" -- case "GPG_AGENT_INFO": -- // not marked as safe -- return ".gpg-agent:0:1" -- case "TERM": -- // not really set -- return "" -- case "PATH": -- // special handling from here down -- return "/something/random:/sbin/:/home/ubuntu/bin:/bin:/snap/bin" -- case "XDG_RUNTIME_DIR": -- return "/some/thing" -- case "LD_PRELOAD": -- return "foo" -- case "LD_LIBRARY_PATH": -- return "bar" -- } -- return "" -- })() -- -- env := strings.Split(errtracker.Environ(), "\n") -- sort.Strings(env) -- -- c.Check(env, DeepEquals, []string{ -- "LD_LIBRARY_PATH=", -- "LD_PRELOAD=", -- // note also /sbin/ -> /sbin -- "PATH=(custom):/sbin:(user):/bin:/snap/bin", -- "SHELL=/bin/sh", -- "XDG_RUNTIME_DIR=", -- }) --} -- --func (s *ErrtrackerTestSuite) TestReportsDB(c *C) { -- db, err := errtracker.NewReportsDB(filepath.Join(s.tmpdir, "foo.db")) -- c.Assert(err, IsNil) -- -- c.Check(db.AlreadyReported("some-dup-sig"), Equals, false) -- -- err = db.MarkReported("some-dup-sig") -- c.Check(err, IsNil) -- -- c.Check(db.AlreadyReported("some-dup-sig"), Equals, true) -- c.Check(db.AlreadyReported("other-dup-sig"), Equals, false) --} -- --func (s *ErrtrackerTestSuite) TestReportsDBCleanup(c *C) { -- db, err := errtracker.NewReportsDB(filepath.Join(s.tmpdir, "foo.db")) -- c.Assert(err, IsNil) -- -- errtracker.SetReportDBCleanupTime(db, 1*time.Millisecond) -- -- err = db.MarkReported("some-dup-sig") -- c.Check(err, IsNil) -- -- time.Sleep(10 * time.Millisecond) -- err = db.MarkReported("other-dup-sig") -- c.Check(err, IsNil) -- -- // this one got cleaned out -- c.Check(db.AlreadyReported("some-dup-sig"), Equals, false) -- // this one is still fresh -- c.Check(db.AlreadyReported("other-dup-sig"), Equals, true) --} -- --func (s *ErrtrackerTestSuite) TestReportsDBnilDoesNotCrash(c *C) { -- db, err := errtracker.NewReportsDB("/proc/1/environ") -- c.Assert(err, NotNil) -- c.Check(db, IsNil) -- -- c.Check(db.AlreadyReported("dupSig"), Equals, false) -- c.Check(db.MarkReported("dupSig"), ErrorMatches, "cannot mark error report as reported with an uninitialized reports database") --} -diff --git a/errtracker/export_test.go b/errtracker/export_test.go -deleted file mode 100644 -index ff3ac0b60..000000000 ---- a/errtracker/export_test.go -+++ /dev/null -@@ -1,126 +0,0 @@ --// -*- Mode: Go; indent-tabs-mode: t -*- -- --/* -- * Copyright (C) 2017 Canonical Ltd -- * -- * This program is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 3 as -- * published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program. If not, see . -- * -- */ -- --package errtracker -- --import ( -- "time" --) -- --func MockCrashDbURL(url string) (restorer func()) { -- old := CrashDbURLBase -- CrashDbURLBase = url -- return func() { -- CrashDbURLBase = old -- } --} -- --func MockMachineIDPaths(paths []string) (restorer func()) { -- old := machineIDs -- machineIDs = paths -- return func() { -- machineIDs = old -- } --} -- --func MockHostSnapd(path string) (restorer func()) { -- old := mockedHostSnapd -- mockedHostSnapd = path -- return func() { -- mockedHostSnapd = old -- } --} -- --func MockCoreSnapd(path string) (restorer func()) { -- old := mockedCoreSnapd -- mockedCoreSnapd = path -- return func() { -- mockedCoreSnapd = old -- } --} -- --func MockTimeNow(f func() time.Time) (restorer func()) { -- old := timeNow -- timeNow = f -- return func() { -- timeNow = old -- } --} -- --func MockReExec(f func() string) (restorer func()) { -- oldDidSnapdReExec := didSnapdReExec -- didSnapdReExec = f -- return func() { -- didSnapdReExec = oldDidSnapdReExec -- } --} -- --func MockOsGetenv(f func(string) string) (restorer func()) { -- old := osGetenv -- osGetenv = f -- return func() { -- osGetenv = old -- } --} -- --func MockProcCpuinfo(filename string) (restorer func()) { -- old := procCpuinfo -- procCpuinfo = filename -- return func() { -- procCpuinfo = old -- } --} -- --func MockProcSelfExe(filename string) (restorer func()) { -- old := procSelfExe -- procSelfExe = filename -- return func() { -- procSelfExe = old -- } --} -- --func MockProcSelfCwd(filename string) (restorer func()) { -- old := procSelfCwd -- procSelfCwd = filename -- return func() { -- procSelfCwd = old -- } --} -- --func MockProcSelfCmdline(filename string) (restorer func()) { -- old := procSelfCmdline -- procSelfCmdline = filename -- return func() { -- procSelfCmdline = old -- } --} -- --var ( -- ProcExe = procExe -- ProcCwd = procCwd -- ProcCmdline = procCmdline -- JournalError = journalError -- ProcCpuinfoMinimal = procCpuinfoMinimal -- Environ = environ -- NewReportsDB = newReportsDB --) -- --func SetReportDBCleanupTime(db *reportsDB, d time.Duration) { -- db.cleanupTime = d --} -diff --git a/packaging/fedora/snapd.spec b/packaging/fedora/snapd.spec -index 390f7966f..fc9515001 100644 ---- a/packaging/fedora/snapd.spec -+++ b/packaging/fedora/snapd.spec -@@ -168,7 +168,6 @@ BuildRequires: golang(golang.org/x/net/context) - BuildRequires: golang(golang.org/x/net/context/ctxhttp) - BuildRequires: golang(gopkg.in/check.v1) - BuildRequires: golang(gopkg.in/macaroon.v1) --BuildRequires: golang(gopkg.in/mgo.v2/bson) - BuildRequires: golang(gopkg.in/retry.v1) - BuildRequires: golang(gopkg.in/tomb.v2) - BuildRequires: golang(gopkg.in/yaml.v2) -@@ -266,7 +265,6 @@ Requires: golang(golang.org/x/net/context) - Requires: golang(golang.org/x/net/context/ctxhttp) - Requires: golang(gopkg.in/check.v1) - Requires: golang(gopkg.in/macaroon.v1) --Requires: golang(gopkg.in/mgo.v2/bson) - Requires: golang(gopkg.in/retry.v1) - Requires: golang(gopkg.in/tomb.v2) - Requires: golang(gopkg.in/yaml.v2) -@@ -295,7 +293,6 @@ Provides: bundled(golang(golang.org/x/net/context)) - Provides: bundled(golang(golang.org/x/net/context/ctxhttp)) - Provides: bundled(golang(gopkg.in/check.v1)) - Provides: bundled(golang(gopkg.in/macaroon.v1)) --Provides: bundled(golang(gopkg.in/mgo.v2/bson)) - Provides: bundled(golang(gopkg.in/retry.v1)) - Provides: bundled(golang(gopkg.in/tomb.v2)) - Provides: bundled(golang(gopkg.in/yaml.v2)) --- -2.20.1 - diff --git a/snapd.spec b/snapd.spec index 7648df0..661cb2d 100644 --- a/snapd.spec +++ b/snapd.spec @@ -86,9 +86,6 @@ Source1: https://%{provider_prefix}/releases/download/%{version}/%{name}_ # Upstream proposed PR: https://github.com/snapcore/snapd/pull/3162 Patch0001: 0001-cmd-use-libtool-for-the-internal-library.patch -# Workaround for MongoDB removal: https://fedoraproject.org/wiki/Changes/MongoDB_Removal -Patch1001: 1001-errtracker-neuter-error-tracker.patch - %if 0%{?with_goarches} # e.g. el6 has ppc64 arch without gcc-go, so EA tag is required ExclusiveArch: %{?go_arches:%{go_arches}}%{!?go_arches:%{ix86} x86_64 %{arm}} @@ -149,8 +146,7 @@ BuildRequires: golang(golang.org/x/net/context) BuildRequires: golang(golang.org/x/net/context/ctxhttp) BuildRequires: golang(gopkg.in/check.v1) BuildRequires: golang(gopkg.in/macaroon.v1) -# FIXME: Address when Patch1001 is addressed -#BuildRequires: golang(gopkg.in/mgo.v2/bson) +BuildRequires: golang(gopkg.in/mgo.v2/bson) BuildRequires: golang(gopkg.in/retry.v1) BuildRequires: golang(gopkg.in/tomb.v2) BuildRequires: golang(gopkg.in/yaml.v2) @@ -245,8 +241,7 @@ Requires: golang(golang.org/x/net/context) Requires: golang(golang.org/x/net/context/ctxhttp) Requires: golang(gopkg.in/check.v1) Requires: golang(gopkg.in/macaroon.v1) -# FIXME: Address when Patch1001 is addressed -#Requires: golang(gopkg.in/mgo.v2/bson) +Requires: golang(gopkg.in/mgo.v2/bson) Requires: golang(gopkg.in/retry.v1) Requires: golang(gopkg.in/tomb.v2) Requires: golang(gopkg.in/yaml.v2)