gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/wrappers/core18_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package wrappers_test 21 22 import ( 23 "fmt" 24 "os" 25 "path/filepath" 26 "syscall" 27 28 . "gopkg.in/check.v1" 29 30 "github.com/snapcore/snapd/dirs" 31 "github.com/snapcore/snapd/logger" 32 "github.com/snapcore/snapd/osutil" 33 "github.com/snapcore/snapd/progress" 34 "github.com/snapcore/snapd/release" 35 "github.com/snapcore/snapd/snap" 36 "github.com/snapcore/snapd/snap/snaptest" 37 "github.com/snapcore/snapd/systemd" 38 "github.com/snapcore/snapd/testutil" 39 "github.com/snapcore/snapd/wrappers" 40 ) 41 42 func makeMockSnapdSnap(c *C) *snap.Info { 43 err := os.MkdirAll(dirs.SnapServicesDir, 0755) 44 c.Assert(err, IsNil) 45 err = os.MkdirAll(dirs.SnapUserServicesDir, 0755) 46 c.Assert(err, IsNil) 47 err = os.MkdirAll(dirs.SnapDBusSystemPolicyDir, 0755) 48 c.Assert(err, IsNil) 49 err = os.MkdirAll(dirs.SnapDBusSessionPolicyDir, 0755) 50 c.Assert(err, IsNil) 51 52 info := snaptest.MockSnapWithFiles(c, snapdYaml, &snap.SideInfo{Revision: snap.R(1)}, [][]string{ 53 // system services 54 {"lib/systemd/system/snapd.service", "[Unit]\n[Service]\nExecStart=/usr/lib/snapd/snapd\n# X-Snapd-Snap: do-not-start"}, 55 {"lib/systemd/system/snapd.system-shutdown.service", "[Unit]\n[Service]\nExecStart=/bin/umount --everything\n# X-Snapd-Snap: do-not-start"}, 56 {"lib/systemd/system/snapd.autoimport.service", "[Unit]\n[Service]\nExecStart=/usr/bin/snap auto-import"}, 57 {"lib/systemd/system/snapd.socket", "[Unit]\n[Socket]\nListenStream=/run/snapd.socket"}, 58 {"lib/systemd/system/snapd.snap-repair.timer", "[Unit]\n[Timer]\nOnCalendar=*-*-* 5,11,17,23:00"}, 59 // user services 60 {"usr/lib/systemd/user/snapd.session-agent.service", "[Unit]\n[Service]\nExecStart=/usr/bin/snap session-agent"}, 61 {"usr/lib/systemd/user/snapd.session-agent.socket", "[Unit]\n[Socket]\nListenStream=%t/snap-session.socket"}, 62 // D-Bus configuration 63 {"usr/share/dbus-1/session.d/snapd.session-services.conf", "<busconfig/>"}, 64 {"usr/share/dbus-1/system.d/snapd.system-services.conf", "<busconfig/>"}, 65 // Extra non-snapd D-Bus config that shouldn't be copied 66 {"usr/share/dbus-1/system.d/io.netplan.Netplan.conf", "<busconfig/>"}, 67 // D-Bus activation files 68 {"usr/share/dbus-1/services/io.snapcraft.Launcher.service", "[D-BUS Service]\nName=io.snapcraft.Launcher"}, 69 {"usr/share/dbus-1/services/io.snapcraft.Settings.service", "[D-BUS Service]\nName=io.snapcraft.Settings"}, 70 {"usr/share/dbus-1/services/io.snapcraft.SessionAgent.service", "[D-BUS Service]\nName=io.snapcraft.SessionAgent"}, 71 }) 72 73 return info 74 } 75 76 type mockSystemctlError struct { 77 msg string 78 exitCode int 79 } 80 81 func (m *mockSystemctlError) Msg() []byte { 82 return []byte(m.msg) 83 } 84 85 func (m *mockSystemctlError) ExitCode() int { 86 return m.exitCode 87 } 88 89 func (m *mockSystemctlError) Error() string { 90 return fmt.Sprintf("mocked systemctl error: code: %v msg: %q", m.exitCode, m.msg) 91 } 92 93 func (s *servicesTestSuite) TestAddSnapServicesForSnapdOnCore(c *C) { 94 restore := release.MockOnClassic(false) 95 defer restore() 96 97 restore = release.MockReleaseInfo(&release.OS{ID: "ubuntu"}) 98 defer restore() 99 100 // reset root dir 101 dirs.SetRootDir(s.tempdir) 102 103 systemctlRestorer := systemd.MockSystemctl(func(cmd ...string) ([]byte, error) { 104 s.sysdLog = append(s.sysdLog, cmd) 105 if cmd[0] == "show" && cmd[1] == "--property=Id,ActiveState,UnitFileState,Type" { 106 s := fmt.Sprintf("Type=oneshot\nId=%s\nActiveState=inactive\nUnitFileState=enabled\n", cmd[2]) 107 return []byte(s), nil 108 } 109 if len(cmd) == 2 && cmd[0] == "is-enabled" { 110 // pretend snapd.socket is disabled 111 if cmd[1] == "snapd.socket" { 112 return []byte("disabled"), &mockSystemctlError{msg: "disabled", exitCode: 1} 113 } 114 return []byte("enabled"), nil 115 } 116 return []byte("ActiveState=inactive\n"), nil 117 }) 118 defer systemctlRestorer() 119 120 info := makeMockSnapdSnap(c) 121 // add the snapd service 122 err := wrappers.AddSnapdSnapServices(info, progress.Null) 123 c.Assert(err, IsNil) 124 125 mountUnit := fmt.Sprintf(`[Unit] 126 Description=Make the snapd snap tooling available for the system 127 Before=snapd.service 128 129 [Mount] 130 What=%s/snap/snapd/1/usr/lib/snapd 131 Where=/usr/lib/snapd 132 Type=none 133 Options=bind 134 135 [Install] 136 WantedBy=snapd.service 137 `, dirs.GlobalRootDir) 138 for _, entry := range [][]string{{ 139 // check that snapd.service is created 140 filepath.Join(dirs.SnapServicesDir, "snapd.service"), 141 // and paths get re-written 142 fmt.Sprintf("[Unit]\n[Service]\nExecStart=%[1]s/snapd/1/usr/lib/snapd/snapd\n# X-Snapd-Snap: do-not-start\n[Unit]\nRequiresMountsFor=%[1]s/snapd/1\n", dirs.SnapMountDir), 143 }, { 144 // check that snapd.autoimport.service is created 145 filepath.Join(dirs.SnapServicesDir, "snapd.autoimport.service"), 146 // and paths get re-written 147 fmt.Sprintf("[Unit]\n[Service]\nExecStart=%[1]s/snapd/1/usr/bin/snap auto-import\n[Unit]\nRequiresMountsFor=%[1]s/snapd/1\n", dirs.SnapMountDir), 148 }, { 149 // check that snapd.system-shutdown.service is created 150 filepath.Join(dirs.SnapServicesDir, "snapd.system-shutdown.service"), 151 // and paths *do not* get re-written 152 "[Unit]\n[Service]\nExecStart=/bin/umount --everything\n# X-Snapd-Snap: do-not-start", 153 }, { 154 // check that usr-lib-snapd.mount is created 155 filepath.Join(dirs.SnapServicesDir, "usr-lib-snapd.mount"), 156 mountUnit, 157 }, { 158 // check that snapd.session-agent.service is created 159 filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.service"), 160 // and paths get re-written 161 fmt.Sprintf("[Unit]\n[Service]\nExecStart=%[1]s/snapd/1/usr/bin/snap session-agent\n[Unit]\nRequiresMountsFor=%[1]s/snapd/1\n", dirs.SnapMountDir), 162 }, { 163 // check that snapd.session-agent.socket is created 164 filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.socket"), 165 "[Unit]\n[Socket]\nListenStream=%t/snap-session.socket", 166 }, { 167 filepath.Join(dirs.SnapDBusSystemPolicyDir, "snapd.system-services.conf"), 168 "<busconfig/>", 169 }, { 170 filepath.Join(dirs.SnapDBusSessionPolicyDir, "snapd.session-services.conf"), 171 "<busconfig/>", 172 }, { 173 filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.Launcher.service"), 174 "[D-BUS Service]\nName=io.snapcraft.Launcher", 175 }, { 176 filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.Settings.service"), 177 "[D-BUS Service]\nName=io.snapcraft.Settings", 178 }, { 179 filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.SessionAgent.service"), 180 "[D-BUS Service]\nName=io.snapcraft.SessionAgent", 181 }} { 182 c.Check(entry[0], testutil.FileEquals, entry[1]) 183 } 184 185 // Non-snapd D-Bus config is not copied 186 c.Check(filepath.Join(dirs.SnapDBusSystemPolicyDir, "io.netplan.Netplan.conf"), testutil.FileAbsent) 187 188 // check the systemctl calls 189 c.Check(s.sysdLog, DeepEquals, [][]string{ 190 {"daemon-reload"}, 191 {"enable", "usr-lib-snapd.mount"}, 192 {"stop", "usr-lib-snapd.mount"}, 193 {"show", "--property=ActiveState", "usr-lib-snapd.mount"}, 194 {"start", "usr-lib-snapd.mount"}, 195 {"daemon-reload"}, 196 {"is-enabled", "snapd.autoimport.service"}, 197 {"is-enabled", "snapd.service"}, 198 {"is-enabled", "snapd.snap-repair.timer"}, 199 // test pretends snapd.socket is disabled and needs enabling 200 {"is-enabled", "snapd.socket"}, 201 {"enable", "snapd.socket"}, 202 {"is-enabled", "snapd.system-shutdown.service"}, 203 {"is-active", "snapd.autoimport.service"}, 204 {"stop", "snapd.autoimport.service"}, 205 {"show", "--property=ActiveState", "snapd.autoimport.service"}, 206 {"start", "snapd.autoimport.service"}, 207 {"is-active", "snapd.snap-repair.timer"}, 208 {"stop", "snapd.snap-repair.timer"}, 209 {"show", "--property=ActiveState", "snapd.snap-repair.timer"}, 210 {"start", "snapd.snap-repair.timer"}, 211 {"is-active", "snapd.socket"}, 212 {"start", "snapd.service"}, 213 {"start", "--no-block", "snapd.seeded.service"}, 214 {"start", "--no-block", "snapd.autoimport.service"}, 215 {"--user", "--global", "disable", "snapd.session-agent.service"}, 216 {"--user", "--global", "enable", "snapd.session-agent.service"}, 217 {"--user", "--global", "disable", "snapd.session-agent.socket"}, 218 {"--user", "--global", "enable", "snapd.session-agent.socket"}, 219 }) 220 } 221 222 func (s *servicesTestSuite) TestAddSnapServicesForSnapdOnClassic(c *C) { 223 restore := release.MockOnClassic(true) 224 defer restore() 225 226 info := makeMockSnapdSnap(c) 227 // add the snapd service 228 err := wrappers.AddSnapdSnapServices(info, progress.Null) 229 c.Assert(err, IsNil) 230 231 // check that snapd services were *not* created 232 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "snapd.service")), Equals, false) 233 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "snapd.autoimport.service")), Equals, false) 234 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "snapd.system-shutdown.service")), Equals, false) 235 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "usr-lib-snapd.mount")), Equals, false) 236 c.Check(osutil.FileExists(filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.service")), Equals, false) 237 c.Check(osutil.FileExists(filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.socket")), Equals, false) 238 c.Check(osutil.FileExists(filepath.Join(dirs.SnapDBusSystemPolicyDir, "snapd.system-services.conf")), Equals, false) 239 c.Check(osutil.FileExists(filepath.Join(dirs.SnapDBusSessionPolicyDir, "snapd.session-services.conf")), Equals, false) 240 c.Check(osutil.FileExists(filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.Launcher.service")), Equals, false) 241 c.Check(osutil.FileExists(filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.Settings.service")), Equals, false) 242 c.Check(osutil.FileExists(filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.SessionAgent.service")), Equals, false) 243 244 // check that no systemctl calls happened 245 c.Check(s.sysdLog, IsNil) 246 } 247 248 func (s *servicesTestSuite) TestAddSessionServicesWithReadOnlyFilesystem(c *C) { 249 restore := release.MockOnClassic(false) 250 defer restore() 251 252 restoreEnsureDirState := wrappers.MockEnsureDirState(func(dir string, glob string, content map[string]osutil.FileState) (changed, removed []string, err error) { 253 return nil, nil, &os.PathError{Err: syscall.EROFS} 254 }) 255 defer restoreEnsureDirState() 256 257 info := makeMockSnapdSnap(c) 258 259 logBuf, restore := logger.MockLogger() 260 defer restore() 261 262 // add the snapd service 263 err := wrappers.AddSnapdSnapServices(info, progress.Null) 264 265 // didn't fail despite of read-only SnapDBusSessionPolicyDir 266 c.Assert(err, IsNil) 267 268 // check that snapd services were *not* created 269 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "snapd.service")), Equals, true) 270 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "snapd.autoimport.service")), Equals, true) 271 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "snapd.system-shutdown.service")), Equals, true) 272 c.Check(osutil.FileExists(filepath.Join(dirs.SnapServicesDir, "usr-lib-snapd.mount")), Equals, true) 273 c.Check(osutil.FileExists(filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.service")), Equals, true) 274 c.Check(osutil.FileExists(filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.socket")), Equals, true) 275 c.Check(osutil.FileExists(filepath.Join(dirs.SnapDBusSystemPolicyDir, "snapd.system-services.conf")), Equals, true) 276 c.Check(osutil.FileExists(filepath.Join(dirs.SnapDBusSessionPolicyDir, "snapd.session-services.conf")), Equals, false) 277 278 c.Assert(logBuf.String(), testutil.Contains, "/etc/dbus-1/session.d appears to be read-only, could not write snapd dbus config files") 279 } 280 281 func (s *servicesTestSuite) TestAddSnapdServicesWithNonSnapd(c *C) { 282 restore := release.MockOnClassic(false) 283 defer restore() 284 285 info := snaptest.MockInfo(c, "name: foo\nversion: 1.0", &snap.SideInfo{}) 286 restore = release.MockReleaseInfo(&release.OS{ID: "ubuntu"}) 287 defer restore() 288 289 err := wrappers.AddSnapdSnapServices(info, progress.Null) 290 c.Assert(err, ErrorMatches, `internal error: adding explicit snapd services for snap "foo" type "app" is unexpected`) 291 } 292 293 func (s *servicesTestSuite) TestRemoveSnapServicesForFirstInstallSnapdOnCore(c *C) { 294 restore := release.MockOnClassic(false) 295 defer restore() 296 297 restore = release.MockReleaseInfo(&release.OS{ID: "ubuntu"}) 298 defer restore() 299 300 // reset root dir 301 dirs.SetRootDir(s.tempdir) 302 303 systemctlRestorer := systemd.MockSystemctl(func(cmd ...string) ([]byte, error) { 304 s.sysdLog = append(s.sysdLog, cmd) 305 if cmd[0] == "show" && cmd[1] == "--property=Id,ActiveState,UnitFileState,Type" { 306 s := fmt.Sprintf("Type=oneshot\nId=%s\nActiveState=inactive\nUnitFileState=enabled\n", cmd[2]) 307 return []byte(s), nil 308 } 309 if len(cmd) == 4 && cmd[2] == "is-enabled" { 310 // pretend snapd.socket is disabled 311 if cmd[3] == "snapd.socket" { 312 return []byte("disabled"), &mockSystemctlError{msg: "disabled", exitCode: 1} 313 } 314 return []byte("enabled"), nil 315 } 316 return []byte("ActiveState=inactive\n"), nil 317 }) 318 defer systemctlRestorer() 319 320 info := makeMockSnapdSnap(c) 321 322 units := [][]string{ 323 {filepath.Join(dirs.SnapServicesDir, "usr-lib-snapd.mount"), "from-snapd"}, 324 {filepath.Join(dirs.SnapServicesDir, "snapd.service"), "from-snapd"}, 325 {filepath.Join(dirs.SnapServicesDir, "snapd.socket"), "from-snapd"}, 326 {filepath.Join(dirs.SnapServicesDir, "snapd.snap-repair.timer"), "from-snapd"}, 327 {filepath.Join(dirs.SnapServicesDir, "snapd.autoimport.service"), "from-snapd"}, 328 {filepath.Join(dirs.SnapServicesDir, "snapd.system-shutdown.service"), "from-snapd"}, 329 {filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.service"), "from-snapd"}, 330 {filepath.Join(dirs.SnapUserServicesDir, "snapd.session-agent.socket"), "from-snapd"}, 331 {filepath.Join(dirs.SnapDBusSystemPolicyDir, "snapd.system-services.conf"), "from-snapd"}, 332 {filepath.Join(dirs.SnapDBusSessionPolicyDir, "snapd.session-services.conf"), "from-snapd"}, 333 // extra unit not present in core snap 334 {filepath.Join(dirs.SnapServicesDir, "snapd.not-in-core.service"), "from-snapd"}, 335 // D-Bus service activation files 336 {filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.Launcher.service"), "from-snapd"}, 337 {filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.Settings.service"), "from-snapd"}, 338 {filepath.Join(dirs.SnapDBusSessionServicesDir, "io.snapcraft.SessionAgent.service"), "from-snapd"}, 339 } 340 // content list uses absolute paths already 341 snaptest.PopulateDir("/", units) 342 343 // add the extra unit to the snap 344 snaptest.PopulateDir("/", [][]string{ 345 {filepath.Join(info.MountDir(), "lib/systemd/system/snapd.not-in-core.service"), "from-snapd"}, 346 }) 347 348 coreUnits := [][]string{ 349 {filepath.Join(dirs.GlobalRootDir, "lib/systemd/system/snapd.service"), "# X-Snapd-Snap: do-not-start"}, 350 {filepath.Join(dirs.GlobalRootDir, "lib/systemd/system/snapd.socket"), "from-core"}, 351 {filepath.Join(dirs.GlobalRootDir, "lib/systemd/system/snapd.snap-repair.timer"), "from-core"}, 352 {filepath.Join(dirs.GlobalRootDir, "lib/systemd/system/snapd.autoimport.service"), "from-core"}, 353 {filepath.Join(dirs.GlobalRootDir, "lib/systemd/system/snapd.system-shutdown.service"), "# X-Snapd-Snap: do-not-start"}, 354 {filepath.Join(dirs.GlobalRootDir, "usr/lib/systemd/user/snapd.session-agent.service"), "from-core"}, 355 {filepath.Join(dirs.GlobalRootDir, "usr/lib/systemd/user/snapd.session-agent.socket"), "from-core"}, 356 } 357 // content list uses absolute paths already 358 snaptest.PopulateDir("/", coreUnits) 359 360 // remove the snapd service 361 err := wrappers.RemoveSnapdSnapServicesOnCore(info, progress.Null) 362 c.Assert(err, IsNil) 363 364 for _, unit := range units { 365 c.Check(unit[0], testutil.FileAbsent) 366 } 367 368 // check the systemctl calls 369 c.Check(s.sysdLog, DeepEquals, [][]string{ 370 // pretend snapd socket needs enabling 371 {"--root", dirs.GlobalRootDir, "is-enabled", "snapd.socket"}, 372 {"--root", dirs.GlobalRootDir, "enable", "snapd.socket"}, 373 374 {"--root", dirs.GlobalRootDir, "is-enabled", "snapd.autoimport.service"}, 375 {"--root", dirs.GlobalRootDir, "is-active", "snapd.autoimport.service"}, 376 {"stop", "snapd.autoimport.service"}, 377 {"show", "--property=ActiveState", "snapd.autoimport.service"}, 378 {"start", "snapd.autoimport.service"}, 379 {"--root", dirs.GlobalRootDir, "disable", "snapd.not-in-core.service"}, 380 {"stop", "snapd.not-in-core.service"}, 381 {"show", "--property=ActiveState", "snapd.not-in-core.service"}, 382 {"--root", dirs.GlobalRootDir, "is-enabled", "snapd.service"}, 383 {"--root", dirs.GlobalRootDir, "is-enabled", "snapd.system-shutdown.service"}, 384 {"--root", dirs.GlobalRootDir, "is-enabled", "snapd.snap-repair.timer"}, 385 {"--root", dirs.GlobalRootDir, "is-active", "snapd.snap-repair.timer"}, 386 {"stop", "snapd.snap-repair.timer"}, 387 {"show", "--property=ActiveState", "snapd.snap-repair.timer"}, 388 {"start", "snapd.snap-repair.timer"}, 389 {"--user", "--global", "--root", dirs.GlobalRootDir, "disable", "snapd.session-agent.service"}, 390 {"--user", "--global", "--root", dirs.GlobalRootDir, "enable", "snapd.session-agent.service"}, 391 {"--user", "--global", "--root", dirs.GlobalRootDir, "disable", "snapd.session-agent.socket"}, 392 {"--user", "--global", "--root", dirs.GlobalRootDir, "enable", "snapd.session-agent.socket"}, 393 {"--root", dirs.GlobalRootDir, "disable", "usr-lib-snapd.mount"}, 394 {"stop", "usr-lib-snapd.mount"}, 395 {"show", "--property=ActiveState", "usr-lib-snapd.mount"}, 396 }) 397 } 398 399 func (s *servicesTestSuite) TestRemoveSnapdServicesWithNonSnapd(c *C) { 400 restore := release.MockOnClassic(false) 401 defer restore() 402 403 info := snaptest.MockInfo(c, "name: foo\nversion: 1.0", &snap.SideInfo{}) 404 restore = release.MockReleaseInfo(&release.OS{ID: "ubuntu"}) 405 defer restore() 406 407 err := wrappers.RemoveSnapdSnapServicesOnCore(info, progress.Null) 408 c.Assert(err, ErrorMatches, `internal error: removing explicit snapd services for snap "foo" type "app" is unexpected`) 409 } 410 411 func (s *servicesTestSuite) TestDeriveSnapdDBusConfig(c *C) { 412 info := makeMockSnapdSnap(c) 413 414 sessionContent, systemContent, err := wrappers.DeriveSnapdDBusConfig(info) 415 c.Assert(err, IsNil) 416 c.Check(sessionContent, DeepEquals, map[string]osutil.FileState{ 417 "snapd.session-services.conf": &osutil.FileReference{ 418 Path: filepath.Join(info.MountDir(), "usr/share/dbus-1/session.d/snapd.session-services.conf"), 419 }, 420 }) 421 c.Check(systemContent, DeepEquals, map[string]osutil.FileState{ 422 "snapd.system-services.conf": &osutil.FileReference{ 423 Path: filepath.Join(info.MountDir(), "usr/share/dbus-1/system.d/snapd.system-services.conf"), 424 }, 425 }) 426 }