Merge ~smoser/ubuntu/+source/snapd:fix/1791691-disable-snapd-env-generator into ubuntu/+source/snapd:ubuntu/devel

Proposed by Scott Moser
Status: Rejected
Rejected by: Scott Moser
Proposed branch: ~smoser/ubuntu/+source/snapd:fix/1791691-disable-snapd-env-generator
Merge into: ubuntu/+source/snapd:ubuntu/devel
Diff against target: 108794 lines (+101894/-3)
1135 files modified
packaging/ubuntu-16.04/changelog (+7/-0)
packaging/ubuntu-16.04/snapd.install (+0/-3)
tests/lib/changes.sh (+8/-0)
tests/lib/dbus.sh (+35/-0)
tests/lib/dirs.sh (+23/-0)
tests/lib/external/prepare-ssh.sh (+15/-0)
tests/lib/fakedevicesvc/main.go (+135/-0)
tests/lib/fakestore/cmd/fakestore/cmd_make_refreshable.go (+39/-0)
tests/lib/fakestore/cmd/fakestore/cmd_new_snap_decl.go (+63/-0)
tests/lib/fakestore/cmd/fakestore/cmd_new_snap_rev.go (+63/-0)
tests/lib/fakestore/cmd/fakestore/cmd_run.go (+70/-0)
tests/lib/fakestore/cmd/fakestore/main.go (+51/-0)
tests/lib/fakestore/refresh/refresh.go (+258/-0)
tests/lib/fakestore/refresh/snap_asserts.go (+95/-0)
tests/lib/fakestore/store/store.go (+720/-0)
tests/lib/fakestore/store/store_test.go (+562/-0)
tests/lib/files.sh (+75/-0)
tests/lib/journalctl.sh (+58/-0)
tests/lib/list-interfaces.go (+10/-0)
tests/lib/mkpinentry.sh (+21/-0)
tests/lib/names.sh (+10/-0)
tests/lib/nested.sh (+68/-0)
tests/lib/network.sh (+34/-0)
tests/lib/os-release.16 (+7/-0)
tests/lib/pinentry-fake.sh (+20/-0)
tests/lib/pkgdb.sh (+733/-0)
tests/lib/prepare-restore.sh (+538/-0)
tests/lib/prepare.sh (+634/-0)
tests/lib/quiet.sh (+30/-0)
tests/lib/ramdisk.sh (+8/-0)
tests/lib/random.sh (+39/-0)
tests/lib/reset.sh (+148/-0)
tests/lib/snaps.sh (+85/-0)
tests/lib/snaps/account-control-consumer/bin/chpasswd (+3/-0)
tests/lib/snaps/account-control-consumer/bin/deluser (+3/-0)
tests/lib/snaps/account-control-consumer/bin/useradd (+3/-0)
tests/lib/snaps/account-control-consumer/meta/snap.yaml (+15/-0)
tests/lib/snaps/aliases/bin/cmd1 (+2/-0)
tests/lib/snaps/aliases/bin/cmd2 (+2/-0)
tests/lib/snaps/aliases/meta/snap.yaml (+9/-0)
tests/lib/snaps/basic-desktop/bin/echo (+3/-0)
tests/lib/snaps/basic-desktop/meta/gui/echo.desktop (+10/-0)
tests/lib/snaps/basic-desktop/meta/snap.yaml (+6/-0)
tests/lib/snaps/basic-hooks/meta/hooks/configure (+7/-0)
tests/lib/snaps/basic-hooks/meta/hooks/invalid-hook (+3/-0)
tests/lib/snaps/basic-hooks/meta/snap.yaml (+11/-0)
tests/lib/snaps/basic-iface-hooks-consumer/meta/hooks/connect-plug-consumer (+62/-0)
tests/lib/snaps/basic-iface-hooks-consumer/meta/hooks/prepare-plug-consumer (+41/-0)
tests/lib/snaps/basic-iface-hooks-consumer/meta/snap.yaml (+7/-0)
tests/lib/snaps/basic-iface-hooks-producer/meta/hooks/connect-slot-producer (+52/-0)
tests/lib/snaps/basic-iface-hooks-producer/meta/hooks/prepare-slot-producer (+35/-0)
tests/lib/snaps/basic-iface-hooks-producer/meta/snap.yaml (+7/-0)
tests/lib/snaps/basic-run/bin/echo (+3/-0)
tests/lib/snaps/basic-run/meta/snap.yaml (+6/-0)
tests/lib/snaps/basic/meta/snap.yaml (+4/-0)
tests/lib/snaps/browser-support-consumer/bin/cmd (+2/-0)
tests/lib/snaps/browser-support-consumer/meta/snap.yaml.in (+10/-0)
tests/lib/snaps/classic-gadget/meta/gadget.yaml (+1/-0)
tests/lib/snaps/classic-gadget/meta/hooks/prepare-device (+2/-0)
tests/lib/snaps/classic-gadget/meta/snap.yaml (+4/-0)
tests/lib/snaps/config-versions-v2/bin/sh (+3/-0)
tests/lib/snaps/config-versions-v2/meta/hooks/configure (+2/-0)
tests/lib/snaps/config-versions-v2/meta/snap.yaml (+7/-0)
tests/lib/snaps/config-versions/bin/sh (+3/-0)
tests/lib/snaps/config-versions/meta/hooks/configure (+2/-0)
tests/lib/snaps/config-versions/meta/snap.yaml (+7/-0)
tests/lib/snaps/data-writer/bin/write-data (+20/-0)
tests/lib/snaps/data-writer/meta/snap.yaml (+9/-0)
tests/lib/snaps/failing-config-hooks/meta/hooks/configure (+4/-0)
tests/lib/snaps/failing-config-hooks/meta/snap.yaml (+2/-0)
tests/lib/snaps/firewall-control-consumer/bin/consumer (+3/-0)
tests/lib/snaps/firewall-control-consumer/meta/snap.yaml (+12/-0)
tests/lib/snaps/generic-consumer/bin/cmd (+5/-0)
tests/lib/snaps/generic-consumer/meta/snap.yaml.in (+6/-0)
tests/lib/snaps/gpio-consumer/bin/read (+3/-0)
tests/lib/snaps/gpio-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/hardware-observe-consumer/bin/consumer (+5/-0)
tests/lib/snaps/hardware-observe-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/home-consumer/bin/reader (+14/-0)
tests/lib/snaps/home-consumer/bin/writer (+15/-0)
tests/lib/snaps/home-consumer/meta/snap.yaml (+12/-0)
tests/lib/snaps/iio-consumer/bin/read (+2/-0)
tests/lib/snaps/iio-consumer/bin/write (+2/-0)
tests/lib/snaps/iio-consumer/meta/snap.yaml (+12/-0)
tests/lib/snaps/locale-control-consumer/bin/get (+14/-0)
tests/lib/snaps/locale-control-consumer/bin/set (+23/-0)
tests/lib/snaps/locale-control-consumer/meta/snap.yaml (+12/-0)
tests/lib/snaps/log-observe-consumer/bin/cmd (+6/-0)
tests/lib/snaps/log-observe-consumer/bin/consumer (+15/-0)
tests/lib/snaps/log-observe-consumer/meta/snap.yaml (+12/-0)
tests/lib/snaps/modem-manager-consumer/bin/consumer (+3/-0)
tests/lib/snaps/modem-manager-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/mount-observe-consumer/bin/consumer (+12/-0)
tests/lib/snaps/mount-observe-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/network-bind-consumer/bin/consumer (+22/-0)
tests/lib/snaps/network-bind-consumer/meta/snap.yaml (+10/-0)
tests/lib/snaps/network-consumer/bin/consumer (+21/-0)
tests/lib/snaps/network-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/network-control-consumer/bin/cmd (+6/-0)
tests/lib/snaps/network-control-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/network-observe-consumer/bin/consumer (+10/-0)
tests/lib/snaps/network-observe-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/process-control-consumer/bin/signal (+6/-0)
tests/lib/snaps/process-control-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/shutdown-introspection-consumer/bin/consumer (+5/-0)
tests/lib/snaps/shutdown-introspection-consumer/meta/snap.yaml (+9/-0)
tests/lib/snaps/snap-hooks-bad-install/meta/hooks/install (+9/-0)
tests/lib/snaps/snap-hooks-bad-install/meta/snap.yaml (+5/-0)
tests/lib/snaps/snap-hooks-bad-install/true (+0/-0)
tests/lib/snaps/snap-hooks/meta/hooks/configure (+3/-0)
tests/lib/snaps/snap-hooks/meta/hooks/install (+3/-0)
tests/lib/snaps/snap-hooks/meta/hooks/post-refresh (+3/-0)
tests/lib/snaps/snap-hooks/meta/hooks/pre-refresh (+3/-0)
tests/lib/snaps/snap-hooks/meta/hooks/remove (+5/-0)
tests/lib/snaps/snap-hooks/meta/snap.yaml (+8/-0)
tests/lib/snaps/snap-hooks/true (+0/-0)
tests/lib/snaps/snap-install-hook-broken/meta/hooks/install (+4/-0)
tests/lib/snaps/snap-install-hook-broken/meta/snap.yaml (+5/-0)
tests/lib/snaps/snapctl-from-snap/bin/snapctl-get (+2/-0)
tests/lib/snaps/snapctl-from-snap/bin/snapctl-set (+2/-0)
tests/lib/snaps/snapctl-from-snap/meta/hooks/configure (+3/-0)
tests/lib/snaps/snapctl-from-snap/meta/snap.yaml (+7/-0)
tests/lib/snaps/snapctl-hooks-v2/meta/hooks/configure (+13/-0)
tests/lib/snaps/snapctl-hooks-v2/meta/snap.yaml (+2/-0)
tests/lib/snaps/snapctl-hooks/meta/hooks/configure (+111/-0)
tests/lib/snaps/snapctl-hooks/meta/snap.yaml (+2/-0)
tests/lib/snaps/socket-activation/bin/sleep (+3/-0)
tests/lib/snaps/socket-activation/meta/snap.yaml (+12/-0)
tests/lib/snaps/test-classic-cgroup/bin/read-fb (+3/-0)
tests/lib/snaps/test-classic-cgroup/bin/read-kmsg (+3/-0)
tests/lib/snaps/test-classic-cgroup/meta/snap.yaml (+12/-0)
tests/lib/snaps/test-devmode-cgroup/bin/read-fb (+3/-0)
tests/lib/snaps/test-devmode-cgroup/bin/read-kmsg (+3/-0)
tests/lib/snaps/test-devmode-cgroup/meta/snap.yaml (+14/-0)
tests/lib/snaps/test-snapd-accounts-service/list-accounts.c (+69/-0)
tests/lib/snaps/test-snapd-accounts-service/snapcraft.yaml (+25/-0)
tests/lib/snaps/test-snapd-after-before-service/bin/start (+6/-0)
tests/lib/snaps/test-snapd-after-before-service/meta/snap.yaml (+16/-0)
tests/lib/snaps/test-snapd-appstreamid/bin/run (+3/-0)
tests/lib/snaps/test-snapd-appstreamid/meta/snap.yaml (+14/-0)
tests/lib/snaps/test-snapd-auto-aliases/bin/wellknown1 (+2/-0)
tests/lib/snaps/test-snapd-auto-aliases/bin/wellknown2 (+2/-0)
tests/lib/snaps/test-snapd-auto-aliases/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-autopilot-consumer/consumer (+22/-0)
tests/lib/snaps/test-snapd-autopilot-consumer/provider.py (+30/-0)
tests/lib/snaps/test-snapd-autopilot-consumer/snapcraft.yaml (+28/-0)
tests/lib/snaps/test-snapd-autopilot-consumer/wrapper (+3/-0)
tests/lib/snaps/test-snapd-base-bare/Makefile (+13/-0)
tests/lib/snaps/test-snapd-base-bare/snapcraft.yaml (+12/-0)
tests/lib/snaps/test-snapd-base/meta/snap.yaml (+4/-0)
tests/lib/snaps/test-snapd-base/random-file (+1/-0)
tests/lib/snaps/test-snapd-broadcom-asic-control/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-broadcom-asic-control/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-busybox-static/snapcraft.yaml (+17/-0)
tests/lib/snaps/test-snapd-check-fs-access/bin/read-dir (+14/-0)
tests/lib/snaps/test-snapd-check-fs-access/bin/read-file (+14/-0)
tests/lib/snaps/test-snapd-check-fs-access/bin/write-dir (+20/-0)
tests/lib/snaps/test-snapd-check-fs-access/bin/write-file (+14/-0)
tests/lib/snaps/test-snapd-check-fs-access/meta/snap.yaml (+18/-0)
tests/lib/snaps/test-snapd-classic-confinement/bin/classic-confinement (+4/-0)
tests/lib/snaps/test-snapd-classic-confinement/bin/recurse (+6/-0)
tests/lib/snaps/test-snapd-classic-confinement/meta/snap.yaml (+8/-0)
tests/lib/snaps/test-snapd-complexion/bin/test-snapd-complexion (+7/-0)
tests/lib/snaps/test-snapd-complexion/meta/snap.yaml (+11/-0)
tests/lib/snaps/test-snapd-complexion/test-snapd-complexion.bash-completer (+31/-0)
tests/lib/snaps/test-snapd-content-advanced-plug/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-content-advanced-plug/meta/snap.yaml (+22/-0)
tests/lib/snaps/test-snapd-content-advanced-slot/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-content-advanced-slot/meta/snap.yaml (+16/-0)
tests/lib/snaps/test-snapd-content-advanced-slot/source/canary (+1/-0)
tests/lib/snaps/test-snapd-content-circular1/bin/content-plug (+6/-0)
tests/lib/snaps/test-snapd-content-circular1/import/.placeholder (+0/-0)
tests/lib/snaps/test-snapd-content-circular1/meta/snap.yaml (+18/-0)
tests/lib/snaps/test-snapd-content-circular2/bin/content-plug (+6/-0)
tests/lib/snaps/test-snapd-content-circular2/import/.placeholder (+0/-0)
tests/lib/snaps/test-snapd-content-circular2/meta/snap.yaml (+18/-0)
tests/lib/snaps/test-snapd-content-mimic-plug/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-content-mimic-plug/dir/stuff-in-dir (+0/-0)
tests/lib/snaps/test-snapd-content-mimic-plug/file (+1/-0)
tests/lib/snaps/test-snapd-content-mimic-plug/meta/snap.yaml (+17/-0)
tests/lib/snaps/test-snapd-content-mimic-plug/symlink (+1/-0)
tests/lib/snaps/test-snapd-content-mimic-plug/symlink-target (+0/-0)
tests/lib/snaps/test-snapd-content-mimic-slot/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-content-mimic-slot/meta/snap.yaml (+11/-0)
tests/lib/snaps/test-snapd-content-mimic-slot/source/canary (+1/-0)
tests/lib/snaps/test-snapd-content-plug-no-content-attr/bin/content-plug (+11/-0)
tests/lib/snaps/test-snapd-content-plug-no-content-attr/import/.placeholder (+0/-0)
tests/lib/snaps/test-snapd-content-plug-no-content-attr/meta/snap.yaml (+11/-0)
tests/lib/snaps/test-snapd-content-plug/bin/content-plug (+11/-0)
tests/lib/snaps/test-snapd-content-plug/import/.placeholder (+0/-0)
tests/lib/snaps/test-snapd-content-plug/meta/snap.yaml (+12/-0)
tests/lib/snaps/test-snapd-content-slot-no-content-attr/meta/snap.yaml (+7/-0)
tests/lib/snaps/test-snapd-content-slot-no-content-attr/shared-content (+3/-0)
tests/lib/snaps/test-snapd-content-slot/meta/snap.yaml (+8/-0)
tests/lib/snaps/test-snapd-content-slot/shared-content (+3/-0)
tests/lib/snaps/test-snapd-content-slot2/meta/snap.yaml (+8/-0)
tests/lib/snaps/test-snapd-content-slot2/shared-content (+3/-0)
tests/lib/snaps/test-snapd-control-consumer/bin/install (+22/-0)
tests/lib/snaps/test-snapd-control-consumer/bin/list (+19/-0)
tests/lib/snaps/test-snapd-control-consumer/meta/snap.yaml (+26/-0)
tests/lib/snaps/test-snapd-cups-control-consumer/snapcraft.yaml (+13/-0)
tests/lib/snaps/test-snapd-daemon-notify/bin/notify (+3/-0)
tests/lib/snaps/test-snapd-daemon-notify/meta/snap.yaml (+10/-0)
tests/lib/snaps/test-snapd-dbus-consumer/consumer.py (+10/-0)
tests/lib/snaps/test-snapd-dbus-consumer/snapcraft.yaml (+25/-0)
tests/lib/snaps/test-snapd-dbus-provider/provider.py (+24/-0)
tests/lib/snaps/test-snapd-dbus-provider/snapcraft.yaml (+23/-0)
tests/lib/snaps/test-snapd-dbus-provider/wrapper (+3/-0)
tests/lib/snaps/test-snapd-desktop/bin/check-dirs (+5/-0)
tests/lib/snaps/test-snapd-desktop/bin/check-files (+5/-0)
tests/lib/snaps/test-snapd-desktop/meta/snap.yaml (+12/-0)
tests/lib/snaps/test-snapd-devmode/meta/snap.yaml (+8/-0)
tests/lib/snaps/test-snapd-devmode/true (+0/-0)
tests/lib/snaps/test-snapd-devpts/bin/openpty (+18/-0)
tests/lib/snaps/test-snapd-devpts/bin/useptmx (+20/-0)
tests/lib/snaps/test-snapd-devpts/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-dvb/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-dvb/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-eds/calendar.c (+201/-0)
tests/lib/snaps/test-snapd-eds/contacts.c (+222/-0)
tests/lib/snaps/test-snapd-eds/meson.build (+14/-0)
tests/lib/snaps/test-snapd-eds/snap/snapcraft.yaml (+47/-0)
tests/lib/snaps/test-snapd-event/bin/read-evdev-device (+29/-0)
tests/lib/snaps/test-snapd-event/meta/snap.yaml (+11/-0)
tests/lib/snaps/test-snapd-framebuffer/bin/read (+3/-0)
tests/lib/snaps/test-snapd-framebuffer/bin/write (+3/-0)
tests/lib/snaps/test-snapd-framebuffer/meta/snap.yaml (+12/-0)
tests/lib/snaps/test-snapd-fuse-consumer/Makefile (+9/-0)
tests/lib/snaps/test-snapd-fuse-consumer/snapcraft.yaml (+18/-0)
tests/lib/snaps/test-snapd-go-webserver/main.go (+25/-0)
tests/lib/snaps/test-snapd-go-webserver/snapcraft.yaml (+19/-0)
tests/lib/snaps/test-snapd-gpg-keys/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-gpg-keys/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-gpg-public-keys/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-gpg-public-keys/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-gpio-memory-control/Makefile (+5/-0)
tests/lib/snaps/test-snapd-gpio-memory-control/gpiomem.c (+59/-0)
tests/lib/snaps/test-snapd-gpio-memory-control/snapcraft.yaml (+17/-0)
tests/lib/snaps/test-snapd-hardware-random-control/bin/check (+5/-0)
tests/lib/snaps/test-snapd-hardware-random-control/meta/snap.yaml (+10/-0)
tests/lib/snaps/test-snapd-hardware-random-observe/bin/check (+5/-0)
tests/lib/snaps/test-snapd-hardware-random-observe/meta/snap.yaml (+10/-0)
tests/lib/snaps/test-snapd-hello-classic/Makefile (+9/-0)
tests/lib/snaps/test-snapd-hello-classic/snapcraft.yaml (+16/-0)
tests/lib/snaps/test-snapd-hello-classic/test-snapd-hello-classic.c (+12/-0)
tests/lib/snaps/test-snapd-joystick/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-joystick/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-kernel-module-control-consumer/snapcraft.yaml (+24/-0)
tests/lib/snaps/test-snapd-kvm/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-kvm/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-layout/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-layout/meta/snap.yaml (+32/-0)
tests/lib/snaps/test-snapd-layout/opt/demo/file (+1/-0)
tests/lib/snaps/test-snapd-layout/usr/share/demo/file (+1/-0)
tests/lib/snaps/test-snapd-libvirt-consumer/bin/machine-down (+3/-0)
tests/lib/snaps/test-snapd-libvirt-consumer/bin/machine-up (+3/-0)
tests/lib/snaps/test-snapd-libvirt-consumer/snapcraft.yaml (+49/-0)
tests/lib/snaps/test-snapd-libvirt-consumer/vm/ping-unikernel.xml (+22/-0)
tests/lib/snaps/test-snapd-location-control-provider/consumer (+22/-0)
tests/lib/snaps/test-snapd-location-control-provider/provider.py (+29/-0)
tests/lib/snaps/test-snapd-location-control-provider/snapcraft.yaml (+26/-0)
tests/lib/snaps/test-snapd-location-control-provider/wrapper (+3/-0)
tests/lib/snaps/test-snapd-multi-service/bin/start (+6/-0)
tests/lib/snaps/test-snapd-multi-service/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-netlink-audit/bin/bind (+15/-0)
tests/lib/snaps/test-snapd-netlink-audit/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-netlink-connector/bin/bind (+15/-0)
tests/lib/snaps/test-snapd-netlink-connector/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-network-status-provider/consumer (+31/-0)
tests/lib/snaps/test-snapd-network-status-provider/provider.py (+33/-0)
tests/lib/snaps/test-snapd-network-status-provider/snapcraft.yaml (+26/-0)
tests/lib/snaps/test-snapd-network-status-provider/wrapper (+3/-0)
tests/lib/snaps/test-snapd-number-version/meta/snap.yaml (+3/-0)
tests/lib/snaps/test-snapd-openvswitch-consumer/bin/ovs-vsctl (+3/-0)
tests/lib/snaps/test-snapd-openvswitch-consumer/snapcraft.yaml (+21/-0)
tests/lib/snaps/test-snapd-openvswitch-support/random-uuid (+3/-0)
tests/lib/snaps/test-snapd-openvswitch-support/snapcraft.yaml (+17/-0)
tests/lib/snaps/test-snapd-password-manager-service-consumer/bin/secret-tool (+3/-0)
tests/lib/snaps/test-snapd-password-manager-service-consumer/snapcraft.yaml (+21/-0)
tests/lib/snaps/test-snapd-physical-memory-observe/bin/head-mem (+3/-0)
tests/lib/snaps/test-snapd-physical-memory-observe/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-policy-app-consumer/bin/run (+10/-0)
tests/lib/snaps/test-snapd-policy-app-consumer/meta/gui/test-desktop.desktop (+6/-0)
tests/lib/snaps/test-snapd-policy-app-consumer/meta/snap.yaml (+356/-0)
tests/lib/snaps/test-snapd-policy-app-provider-classic/bin/run (+10/-0)
tests/lib/snaps/test-snapd-policy-app-provider-classic/meta/snap.yaml (+99/-0)
tests/lib/snaps/test-snapd-policy-app-provider-core/bin/run (+10/-0)
tests/lib/snaps/test-snapd-policy-app-provider-core/meta/snap.yaml (+139/-0)
tests/lib/snaps/test-snapd-private/meta/snap.yaml (+6/-0)
tests/lib/snaps/test-snapd-public/meta/snap.yaml (+6/-0)
tests/lib/snaps/test-snapd-python-webserver/index.html (+43/-0)
tests/lib/snaps/test-snapd-python-webserver/server.py (+46/-0)
tests/lib/snaps/test-snapd-python-webserver/snapcraft.yaml (+21/-0)
tests/lib/snaps/test-snapd-raw-usb/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-raw-usb/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-removable-media/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-removable-media/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-requires-base-bare/meta/snap.yaml (+4/-0)
tests/lib/snaps/test-snapd-requires-base/meta/snap.yaml (+4/-0)
tests/lib/snaps/test-snapd-rsync/snapcraft.yaml (+16/-0)
tests/lib/snaps/test-snapd-service-try-v1/bin/service (+3/-0)
tests/lib/snaps/test-snapd-service-try-v1/meta/snap.yaml (+5/-0)
tests/lib/snaps/test-snapd-service-try-v2/bin/service (+3/-0)
tests/lib/snaps/test-snapd-service-try-v2/meta/snap.yaml (+6/-0)
tests/lib/snaps/test-snapd-service-v1-good/bin/good (+3/-0)
tests/lib/snaps/test-snapd-service-v1-good/meta/snap.yaml (+7/-0)
tests/lib/snaps/test-snapd-service-v2-bad/bin/bad (+4/-0)
tests/lib/snaps/test-snapd-service-v2-bad/meta/snap.yaml (+7/-0)
tests/lib/snaps/test-snapd-service-watchdog/bin/direct (+58/-0)
tests/lib/snaps/test-snapd-service-watchdog/meta/snap.yaml (+15/-0)
tests/lib/snaps/test-snapd-service/bin/reload (+8/-0)
tests/lib/snaps/test-snapd-service/bin/start (+9/-0)
tests/lib/snaps/test-snapd-service/bin/start-other (+6/-0)
tests/lib/snaps/test-snapd-service/bin/start-stop-mode (+66/-0)
tests/lib/snaps/test-snapd-service/bin/start-stop-mode-sigterm (+15/-0)
tests/lib/snaps/test-snapd-service/bin/stop (+7/-0)
tests/lib/snaps/test-snapd-service/bin/stop-stop-mode (+4/-0)
tests/lib/snaps/test-snapd-service/meta/hooks/configure (+19/-0)
tests/lib/snaps/test-snapd-service/meta/snap.yaml (+59/-0)
tests/lib/snaps/test-snapd-sh/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-sh/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-ssh-keys/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-ssh-keys/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-ssh-public-keys/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-ssh-public-keys/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-snapd-system-observe-consumer/consumer.py (+11/-0)
tests/lib/snaps/test-snapd-system-observe-consumer/dbus-introspect.py (+10/-0)
tests/lib/snaps/test-snapd-system-observe-consumer/snapcraft.yaml (+25/-0)
tests/lib/snaps/test-snapd-timedate-control-consumer/bin/hwclock (+2/-0)
tests/lib/snaps/test-snapd-timedate-control-consumer/bin/timedatectl (+2/-0)
tests/lib/snaps/test-snapd-timedate-control-consumer/meta/snap.yaml (+18/-0)
tests/lib/snaps/test-snapd-timer-service/bin/loop (+10/-0)
tests/lib/snaps/test-snapd-timer-service/meta/snap.yaml (+13/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/block (+14/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/cat (+3/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/cmd (+6/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/echo (+3/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/env (+3/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/fail (+3/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/head (+3/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/sh (+13/-0)
tests/lib/snaps/test-snapd-tools-core18/bin/success (+3/-0)
tests/lib/snaps/test-snapd-tools-core18/meta/snap.yaml (+30/-0)
tests/lib/snaps/test-snapd-tools/bin/block (+14/-0)
tests/lib/snaps/test-snapd-tools/bin/cat (+3/-0)
tests/lib/snaps/test-snapd-tools/bin/cmd (+6/-0)
tests/lib/snaps/test-snapd-tools/bin/echo (+3/-0)
tests/lib/snaps/test-snapd-tools/bin/env (+3/-0)
tests/lib/snaps/test-snapd-tools/bin/fail (+3/-0)
tests/lib/snaps/test-snapd-tools/bin/head (+3/-0)
tests/lib/snaps/test-snapd-tools/bin/sh (+13/-0)
tests/lib/snaps/test-snapd-tools/bin/success (+3/-0)
tests/lib/snaps/test-snapd-tools/meta/snap.yaml (+29/-0)
tests/lib/snaps/test-snapd-tuntap/bin/tuntap.py (+79/-0)
tests/lib/snaps/test-snapd-tuntap/meta/snap.yaml (+10/-0)
tests/lib/snaps/test-snapd-udev-input-subsystem/bin/read-evdev-kbd (+24/-0)
tests/lib/snaps/test-snapd-udev-input-subsystem/meta/snap.yaml (+24/-0)
tests/lib/snaps/test-snapd-uhid/Makefile (+5/-0)
tests/lib/snaps/test-snapd-uhid/snapcraft.yaml (+17/-0)
tests/lib/snaps/test-snapd-uhid/uhid-test.c (+190/-0)
tests/lib/snaps/test-snapd-unknown-interfaces/bin/sh (+3/-0)
tests/lib/snaps/test-snapd-unknown-interfaces/meta/snap.yaml (+10/-0)
tests/lib/snaps/test-snapd-upower-observe-consumer/snapcraft.yaml (+14/-0)
tests/lib/snaps/test-snapd-validate-container-failures/bin/bar (+0/-0)
tests/lib/snaps/test-snapd-validate-container-failures/bin/foo (+0/-0)
tests/lib/snaps/test-snapd-validate-container-failures/comp.sh (+0/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/bar (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/bar -> baz (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/bar -> baz -> qux (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/bar -> qux (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/baz (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/baz -> qux (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/foo (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/foo -> bar (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/foo -> bar -> baz (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/foo -> bar -> qux (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/foo -> baz (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/foo -> baz -> qux (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/foo -> qux (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/hell/qux (+1/-0)
tests/lib/snaps/test-snapd-validate-container-failures/meta/hooks/what (+0/-0)
tests/lib/snaps/test-snapd-validate-container-failures/meta/snap.yaml (+11/-0)
tests/lib/snaps/test-snapd-validate-container-failures/meta/unreadable (+0/-0)
tests/lib/snaps/test-snapd-with-configure/meta/hooks/configure (+2/-0)
tests/lib/snaps/test-snapd-with-configure/meta/snap.yaml (+4/-0)
tests/lib/snaps/test-snapd-xdg-autostart/bin/foobar (+26/-0)
tests/lib/snaps/test-snapd-xdg-autostart/meta/snap.yaml (+6/-0)
tests/lib/snaps/test-snapd-xdg-settings/bin/browser (+3/-0)
tests/lib/snaps/test-snapd-xdg-settings/bin/set-default-web-browser (+5/-0)
tests/lib/snaps/test-snapd-xdg-settings/meta/gui/browser.desktop (+6/-0)
tests/lib/snaps/test-snapd-xdg-settings/meta/snap.yaml (+9/-0)
tests/lib/snaps/test-strict-cgroup/bin/read-fb (+3/-0)
tests/lib/snaps/test-strict-cgroup/bin/read-kmsg (+3/-0)
tests/lib/snaps/test-strict-cgroup/meta/snap.yaml (+14/-0)
tests/lib/spread-funcs.sh (+14/-0)
tests/lib/state.sh (+122/-0)
tests/lib/store.sh (+100/-0)
tests/lib/strings.sh (+5/-0)
tests/lib/successful_login.exp (+13/-0)
tests/lib/systemd-escape/main.go (+52/-0)
tests/lib/systemd.sh (+62/-0)
tests/lib/systems.sh (+29/-0)
tests/main/abort/task.yaml (+44/-0)
tests/main/ack/alice.account (+19/-0)
tests/main/ack/alice.account-key (+31/-0)
tests/main/ack/bob.assertions (+51/-0)
tests/main/ack/task.yaml (+31/-0)
tests/main/alias/task.yaml (+57/-0)
tests/main/appstream-id/task.yaml (+30/-0)
tests/main/apt-hooks/task.yaml (+46/-0)
tests/main/auth-errors/task.yaml (+26/-0)
tests/main/auto-aliases/task.yaml (+38/-0)
tests/main/auto-refresh-private/expired_macaroons.sh (+13/-0)
tests/main/auto-refresh-private/successful_login.exp (+13/-0)
tests/main/auto-refresh-private/task.yaml (+112/-0)
tests/main/auto-refresh/task.yaml (+67/-0)
tests/main/base-snaps-refresh/task.yaml (+21/-0)
tests/main/base-snaps/task.yaml (+44/-0)
tests/main/canonical-livepatch/task.yaml (+28/-0)
tests/main/catalog-update/task.yaml (+27/-0)
tests/main/cgroup-freezer/task.yaml (+45/-0)
tests/main/change-errors/task.yaml (+10/-0)
tests/main/chattr/task.yaml (+19/-0)
tests/main/chattr/toggle.go (+51/-0)
tests/main/classic-confinement-not-supported/task.yaml (+40/-0)
tests/main/classic-confinement/task.yaml (+56/-0)
tests/main/classic-custom-device-reg/task.yaml (+80/-0)
tests/main/classic-firstboot/task.yaml (+75/-0)
tests/main/classic-ubuntu-core-transition-auth/task.yaml (+70/-0)
tests/main/classic-ubuntu-core-transition-two-cores/task.yaml (+75/-0)
tests/main/classic-ubuntu-core-transition/task.yaml (+127/-0)
tests/main/cmdline/task.yaml (+10/-0)
tests/main/completion/abort.exp (+7/-0)
tests/main/completion/ack.exp (+8/-0)
tests/main/completion/alias.exp (+13/-0)
tests/main/completion/buy.exp (+8/-0)
tests/main/completion/change.exp (+7/-0)
tests/main/completion/delete-key.exp (+6/-0)
tests/main/completion/disable.exp (+6/-0)
tests/main/completion/download.exp (+7/-0)
tests/main/completion/enable.exp (+6/-0)
tests/main/completion/export-key.exp (+6/-0)
tests/main/completion/get.exp (+6/-0)
tests/main/completion/info.exp (+11/-0)
tests/main/completion/install.exp (+22/-0)
tests/main/completion/key.exp0 (+17/-0)
tests/main/completion/lib.exp0 (+1/-0)
tests/main/completion/list.exp (+7/-0)
tests/main/completion/refresh.exp (+6/-0)
tests/main/completion/remove.exp (+6/-0)
tests/main/completion/revert.exp (+6/-0)
tests/main/completion/set.exp (+6/-0)
tests/main/completion/sign-build.exp (+6/-0)
tests/main/completion/sign.exp (+6/-0)
tests/main/completion/task.yaml (+54/-0)
tests/main/completion/toplevel.exp (+11/-0)
tests/main/completion/try.exp (+6/-0)
tests/main/completion/watch.exp (+7/-0)
tests/main/config-versions/task.yaml (+64/-0)
tests/main/confinement-classic/task.yaml (+44/-0)
tests/main/core-snap-not-test-test/task.yaml (+5/-0)
tests/main/core-snap-refresh-on-core/task.yaml (+123/-0)
tests/main/core-snap-refresh/task.yaml (+53/-0)
tests/main/core-watchdog/task.yaml (+31/-0)
tests/main/create-key/passphrase_mismatch.exp (+17/-0)
tests/main/create-key/successful_default.exp (+48/-0)
tests/main/create-key/successful_non_default.exp (+48/-0)
tests/main/create-key/task.yaml (+26/-0)
tests/main/create-user/task.yaml (+41/-0)
tests/main/debs-have-built-using/task.yaml (+12/-0)
tests/main/debug-confinement/task.yaml (+12/-0)
tests/main/debug-paths/task.yaml (+13/-0)
tests/main/debug-sandbox/task.yaml (+25/-0)
tests/main/degraded/task.yaml (+17/-0)
tests/main/dirs-not-shared-with-host/task.yaml (+32/-0)
tests/main/disable-autoconnect/task.yaml (+48/-0)
tests/main/econnreset/task.yaml (+67/-0)
tests/main/enable-disable-units-gpio/task.yaml (+91/-0)
tests/main/enable-disable/task.yaml (+50/-0)
tests/main/failover/task.yaml (+125/-0)
tests/main/fakestore-install/task.yaml (+38/-0)
tests/main/fedora-base-smoke/task.yaml (+13/-0)
tests/main/find-private/task.yaml (+51/-0)
tests/main/generic-classic-reg/task.yaml (+26/-0)
tests/main/help/task.yaml (+22/-0)
tests/main/high-user-handling/task.yaml (+12/-0)
tests/main/high-user-handling/test.go (+16/-0)
tests/main/i18n/task.yaml (+26/-0)
tests/main/install-cache/task.yaml (+10/-0)
tests/main/install-closed-channel/task.yaml (+9/-0)
tests/main/install-errors/task.yaml (+90/-0)
tests/main/install-refresh-private/task.yaml (+52/-0)
tests/main/install-refresh-remove-hooks/task.yaml (+77/-0)
tests/main/install-remove-multi/task.yaml (+12/-0)
tests/main/install-sideload/task.yaml (+81/-0)
tests/main/install-snaps/task.yaml (+124/-0)
tests/main/install-socket-activation/task.yaml (+17/-0)
tests/main/install-store-laaaarge/task.yaml (+22/-0)
tests/main/install-store/task.yaml (+47/-0)
tests/main/interfaces-account-control/task.yaml (+32/-0)
tests/main/interfaces-accounts-service/task.yaml (+63/-0)
tests/main/interfaces-alsa/task.yaml (+95/-0)
tests/main/interfaces-autopilot-introspection/task.yaml (+83/-0)
tests/main/interfaces-avahi-observe/task.yaml (+46/-0)
tests/main/interfaces-bluetooth-control/task.yaml (+60/-0)
tests/main/interfaces-bluez/task.yaml (+19/-0)
tests/main/interfaces-broadcom-asic-control/task.yaml (+86/-0)
tests/main/interfaces-browser-support/task.yaml (+158/-0)
tests/main/interfaces-calendar-service/task.yaml (+81/-0)
tests/main/interfaces-cli/task.yaml (+25/-0)
tests/main/interfaces-contacts-service/task.yaml (+104/-0)
tests/main/interfaces-content-circular/task.yaml (+18/-0)
tests/main/interfaces-content-default-provider/task.yaml (+23/-0)
tests/main/interfaces-content-empty-content-attr/task.yaml (+34/-0)
tests/main/interfaces-content-mimic/task.yaml (+63/-0)
tests/main/interfaces-content-mkdir-writable/task.yaml (+103/-0)
tests/main/interfaces-content/task.yaml (+56/-0)
tests/main/interfaces-cups-control/task.yaml (+75/-0)
tests/main/interfaces-daemon-notify/task.yaml (+52/-0)
tests/main/interfaces-dbus/task.yaml (+64/-0)
tests/main/interfaces-desktop-document-portal/task.yaml (+60/-0)
tests/main/interfaces-desktop-host-fonts/task.yaml (+45/-0)
tests/main/interfaces-desktop/task.yaml (+51/-0)
tests/main/interfaces-dvb/task.yaml (+52/-0)
tests/main/interfaces-firewall-control/task.yaml (+86/-0)
tests/main/interfaces-framebuffer/task.yaml (+49/-0)
tests/main/interfaces-fuse_support/task.yaml (+88/-0)
tests/main/interfaces-gpg-keys/task.yaml (+74/-0)
tests/main/interfaces-gpg-public-keys/task.yaml (+71/-0)
tests/main/interfaces-gpio-memory-control/task.yaml (+43/-0)
tests/main/interfaces-hardware-observe/task.yaml (+44/-0)
tests/main/interfaces-hardware-random-control/task.yaml (+56/-0)
tests/main/interfaces-hardware-random-observe/task.yaml (+56/-0)
tests/main/interfaces-home/task.yaml (+125/-0)
tests/main/interfaces-hooks-misbehaving/task.yaml (+11/-0)
tests/main/interfaces-hooks/task.yaml (+58/-0)
tests/main/interfaces-iio/task.yaml (+50/-0)
tests/main/interfaces-joystick/task.yaml (+68/-0)
tests/main/interfaces-kernel-module-control/task.yaml (+123/-0)
tests/main/interfaces-kvm/task.yaml (+47/-0)
tests/main/interfaces-libvirt/task.yaml (+69/-0)
tests/main/interfaces-locale-control/task.yaml (+98/-0)
tests/main/interfaces-location-control/task.yaml (+67/-0)
tests/main/interfaces-log-observe/task.yaml (+49/-0)
tests/main/interfaces-many/task.yaml (+115/-0)
tests/main/interfaces-mount-observe/task.yaml (+56/-0)
tests/main/interfaces-netlink-audit/task.yaml (+41/-0)
tests/main/interfaces-netlink-connector/task.yaml (+36/-0)
tests/main/interfaces-network-bind/task.yaml (+60/-0)
tests/main/interfaces-network-control-ip-netns/task.yaml (+43/-0)
tests/main/interfaces-network-control-tuntap/task.yaml (+43/-0)
tests/main/interfaces-network-control/task.yaml (+144/-0)
tests/main/interfaces-network-manager/task.yaml (+53/-0)
tests/main/interfaces-network-observe/task.yaml (+61/-0)
tests/main/interfaces-network-setup-control/task.yaml (+56/-0)
tests/main/interfaces-network-setup-observe/task.yaml (+54/-0)
tests/main/interfaces-network-status/task.yaml (+65/-0)
tests/main/interfaces-network/task.yaml (+65/-0)
tests/main/interfaces-opengl-nvidia/task.yaml (+119/-0)
tests/main/interfaces-openvswitch-support/task.yaml (+46/-0)
tests/main/interfaces-openvswitch/task.yaml (+113/-0)
tests/main/interfaces-password-manager-service/task.yaml (+47/-0)
tests/main/interfaces-physical-memory-observe/task.yaml (+48/-0)
tests/main/interfaces-process-control/task.yaml (+60/-0)
tests/main/interfaces-raw-usb/task.yaml (+52/-0)
tests/main/interfaces-removable-media/task.yaml (+88/-0)
tests/main/interfaces-shutdown-introspection/task.yaml (+43/-0)
tests/main/interfaces-snapd-control-with-manage/task.yaml (+134/-0)
tests/main/interfaces-snapd-control/task.yaml (+46/-0)
tests/main/interfaces-ssh-keys/task.yaml (+57/-0)
tests/main/interfaces-ssh-public-keys/task.yaml (+63/-0)
tests/main/interfaces-system-observe/task.yaml (+65/-0)
tests/main/interfaces-time-control/task.yaml (+65/-0)
tests/main/interfaces-timeserver-control/task.yaml (+75/-0)
tests/main/interfaces-timezone-control/task.yaml (+64/-0)
tests/main/interfaces-udev/task.yaml (+29/-0)
tests/main/interfaces-uhid/task.yaml (+45/-0)
tests/main/interfaces-upower-observe/task.yaml (+65/-0)
tests/main/interfaces-wayland/task.yaml (+59/-0)
tests/main/kernel-snap-refresh-on-core/task.yaml (+116/-0)
tests/main/known-remote/task.yaml (+8/-0)
tests/main/known/task.yaml (+15/-0)
tests/main/layout/task.yaml (+83/-0)
tests/main/listing/task.yaml (+49/-0)
tests/main/local-install-w-metadata/digest.go (+17/-0)
tests/main/local-install-w-metadata/task.yaml (+23/-0)
tests/main/login/missing_email_error.exp (+9/-0)
tests/main/login/task.yaml (+33/-0)
tests/main/login/unsuccessful_login.exp (+14/-0)
tests/main/lxd/task.yaml (+113/-0)
tests/main/manpages/task.yaml (+31/-0)
tests/main/media-sharing/task.yaml (+25/-0)
tests/main/nfs-support/task.yaml (+119/-0)
tests/main/op-install-failed-undone/task.yaml (+53/-0)
tests/main/op-remove-retry/task.yaml (+42/-0)
tests/main/op-remove/task.yaml (+43/-0)
tests/main/postrm-purge/task.yaml (+36/-0)
tests/main/prefer/task.yaml (+34/-0)
tests/main/prepare-image-grub-core18/task.yaml (+83/-0)
tests/main/prepare-image-grub/task.yaml (+84/-0)
tests/main/prepare-image-uboot/task.yaml (+77/-0)
tests/main/refresh-all-undo/task.yaml (+80/-0)
tests/main/refresh-all/task.yaml (+62/-0)
tests/main/refresh-amend/task.yaml (+28/-0)
tests/main/refresh-delta-from-core/task.yaml (+30/-0)
tests/main/refresh-delta/task.yaml (+29/-0)
tests/main/refresh-devmode/task.yaml (+87/-0)
tests/main/refresh-hold/task.yaml (+20/-0)
tests/main/refresh-undo/task.yaml (+50/-0)
tests/main/refresh/task.yaml (+131/-0)
tests/main/regression-home-snap-root-owned/task.yaml (+34/-0)
tests/main/remove-errors/task.yaml (+18/-0)
tests/main/revert-devmode/task.yaml (+92/-0)
tests/main/revert-sideload/task.yaml (+20/-0)
tests/main/revert/task.yaml (+109/-0)
tests/main/searching/task.yaml (+72/-0)
tests/main/security-apparmor/task.yaml (+22/-0)
tests/main/security-dev-input-event-denied/task.yaml (+65/-0)
tests/main/security-device-cgroups-classic/task.yaml (+37/-0)
tests/main/security-device-cgroups-devmode/task.yaml (+42/-0)
tests/main/security-device-cgroups-jailmode/task.yaml (+45/-0)
tests/main/security-device-cgroups-serial-port/task.yaml (+61/-0)
tests/main/security-device-cgroups-strict/task.yaml (+44/-0)
tests/main/security-device-cgroups/task.yaml (+130/-0)
tests/main/security-devpts/task.yaml (+30/-0)
tests/main/security-private-tmp/task.yaml (+49/-0)
tests/main/security-private-tmp/tmp-create.exp (+15/-0)
tests/main/security-profiles/task.yaml (+31/-0)
tests/main/security-setuid-root/task.yaml (+43/-0)
tests/main/security-udev-input-subsystem/task.yaml (+87/-0)
tests/main/server-snap/task.yaml (+39/-0)
tests/main/set-proxy-store/task.yaml (+74/-0)
tests/main/snap-advise-command/task.yaml (+50/-0)
tests/main/snap-auto-import-asserts-spools/task.yaml (+54/-0)
tests/main/snap-auto-import-asserts/task.yaml (+38/-0)
tests/main/snap-auto-mount/task.yaml (+56/-0)
tests/main/snap-confine-from-core/task.yaml (+69/-0)
tests/main/snap-confine-privs/task.yaml (+63/-0)
tests/main/snap-confine-privs/uids-and-gids.c (+40/-0)
tests/main/snap-confine/task.yaml (+52/-0)
tests/main/snap-connect/task.yaml (+65/-0)
tests/main/snap-connectivity-check/task.yaml (+5/-0)
tests/main/snap-core-fixup/task.yaml (+46/-0)
tests/main/snap-core-symlinks/task.yaml (+13/-0)
tests/main/snap-debug-get-base-declaration/task.yaml (+9/-0)
tests/main/snap-discard-ns/task.yaml (+36/-0)
tests/main/snap-disconnect/task.yaml (+45/-0)
tests/main/snap-download/task.yaml (+35/-0)
tests/main/snap-env/task.yaml (+61/-0)
tests/main/snap-get/task.yaml (+106/-0)
tests/main/snap-info/check.py (+144/-0)
tests/main/snap-info/task.yaml (+49/-0)
tests/main/snap-interface/snap-interface-network.yaml (+6/-0)
tests/main/snap-interface/task.yaml (+14/-0)
tests/main/snap-logs/task.yaml (+37/-0)
tests/main/snap-mgmt/task.yaml (+84/-0)
tests/main/snap-multi-service-failing/task.yaml (+10/-0)
tests/main/snap-readme/task.yaml (+10/-0)
tests/main/snap-remove-not-mounted/task.yaml (+15/-0)
tests/main/snap-repair/task.yaml (+22/-0)
tests/main/snap-run-alias/task.yaml (+36/-0)
tests/main/snap-run-hook/task.yaml (+50/-0)
tests/main/snap-run-symlink-error/task.yaml (+22/-0)
tests/main/snap-run-symlink/task.yaml (+31/-0)
tests/main/snap-run-userdata-current/task.yaml (+40/-0)
tests/main/snap-run/task.yaml (+63/-0)
tests/main/snap-seccomp/task.yaml (+141/-0)
tests/main/snap-service-after-before/task.yaml (+19/-0)
tests/main/snap-service-refresh-mode/task.yaml (+35/-0)
tests/main/snap-service-stop-mode-sigkill/task.yaml (+42/-0)
tests/main/snap-service-stop-mode/task.yaml (+67/-0)
tests/main/snap-service-timer/task.yaml (+51/-0)
tests/main/snap-service-watchdog/task.yaml (+51/-0)
tests/main/snap-service/task.yaml (+28/-0)
tests/main/snap-set-core-w-no-core/task.yaml (+22/-0)
tests/main/snap-set/task.yaml (+59/-0)
tests/main/snap-sign/create-key.exp (+17/-0)
tests/main/snap-sign/sign-model.exp (+20/-0)
tests/main/snap-sign/task.yaml (+46/-0)
tests/main/snap-switch/task.yaml (+8/-0)
tests/main/snap-system-env/task.yaml (+35/-0)
tests/main/snap-system-key/task.yaml (+78/-0)
tests/main/snap-update-ns/task.yaml (+77/-0)
tests/main/snap-userd-desktop-app-autostart/task.yaml (+36/-0)
tests/main/snap-userd-reexec/task.yaml (+17/-0)
tests/main/snap-wait/task.yaml (+26/-0)
tests/main/snapctl-configure-core/task.yaml (+78/-0)
tests/main/snapctl-from-snap/task.yaml (+90/-0)
tests/main/snapctl-services/task.yaml (+85/-0)
tests/main/snapctl/task.yaml (+48/-0)
tests/main/snapd-notify/task.yaml (+37/-0)
tests/main/snapd-reexec/task.yaml (+97/-0)
tests/main/snapd-snap/task.yaml (+16/-0)
tests/main/stale-base-snap/task.yaml (+67/-0)
tests/main/static/task.yaml (+5/-0)
tests/main/system-core-alias/task.yaml (+19/-0)
tests/main/systemd-service/task.yaml (+20/-0)
tests/main/try-non-fatal/task.yaml (+19/-0)
tests/main/try-snap-goes-away/task.yaml (+47/-0)
tests/main/try-snap-is-optional/task.yaml (+9/-0)
tests/main/try-twice-with-daemon/task.yaml (+35/-0)
tests/main/try/task.yaml (+92/-0)
tests/main/ubuntu-core-apt/task.yaml (+9/-0)
tests/main/ubuntu-core-classic/task.yaml (+49/-0)
tests/main/ubuntu-core-create-user/task.yaml (+47/-0)
tests/main/ubuntu-core-custom-device-reg-extras/manip_seed.py (+21/-0)
tests/main/ubuntu-core-custom-device-reg-extras/prepare-device (+5/-0)
tests/main/ubuntu-core-custom-device-reg-extras/task.yaml (+81/-0)
tests/main/ubuntu-core-custom-device-reg/manip_seed.py (+21/-0)
tests/main/ubuntu-core-custom-device-reg/prepare-device (+2/-0)
tests/main/ubuntu-core-custom-device-reg/task.yaml (+79/-0)
tests/main/ubuntu-core-device-reg/task.yaml (+28/-0)
tests/main/ubuntu-core-fan/task.yaml (+16/-0)
tests/main/ubuntu-core-gadget-config-defaults/manip_seed.py (+27/-0)
tests/main/ubuntu-core-gadget-config-defaults/task.yaml (+116/-0)
tests/main/ubuntu-core-grub/task.yaml (+12/-0)
tests/main/ubuntu-core-network-config/task.yaml (+30/-0)
tests/main/ubuntu-core-os-release/task.yaml (+5/-0)
tests/main/ubuntu-core-reboot/task.yaml (+40/-0)
tests/main/ubuntu-core-services/task.yaml (+17/-0)
tests/main/ubuntu-core-uboot/task.yaml (+12/-0)
tests/main/ubuntu-core-upgrade/task.yaml (+92/-0)
tests/main/ubuntu-core-writablepaths/task.yaml (+38/-0)
tests/main/unhandled-task/task.yaml (+30/-0)
tests/main/user-data-handling/task.yaml (+34/-0)
tests/main/user-mounts/task.yaml (+48/-0)
tests/main/validate-container-failures/task.yaml (+32/-0)
tests/main/whoami/task.yaml (+19/-0)
tests/main/writable-areas/task.yaml (+37/-0)
tests/main/xauth-migration/task.yaml (+85/-0)
tests/main/xdg-open-compat/task.yaml (+103/-0)
tests/main/xdg-open/task.yaml (+73/-0)
tests/main/xdg-settings/task.yaml (+88/-0)
tests/manual-tests.md (+236/-0)
tests/nested/core-revert/task.yaml (+73/-0)
tests/nested/extra-snaps-assertions/task.yaml (+67/-0)
tests/nested/image-build/task.yaml (+25/-0)
tests/nightly/docker/task.yaml (+37/-0)
tests/nightly/unity/task.yaml (+31/-0)
tests/regression/lp-1595444/task.yaml (+37/-0)
tests/regression/lp-1597839/task.yaml (+13/-0)
tests/regression/lp-1597842/task.yaml (+23/-0)
tests/regression/lp-1599891/task.yaml (+14/-0)
tests/regression/lp-1606277/task.yaml (+13/-0)
tests/regression/lp-1607796/task.yaml (+12/-0)
tests/regression/lp-1613845/task.yaml (+22/-0)
tests/regression/lp-1615113/task.yaml (+13/-0)
tests/regression/lp-1618683/task.yaml (+13/-0)
tests/regression/lp-1630479/task.yaml (+27/-0)
tests/regression/lp-1641885/task.yaml (+32/-0)
tests/regression/lp-1644439/task.yaml (+48/-0)
tests/regression/lp-1665004/task.yaml (+15/-0)
tests/regression/lp-1667385/task.yaml (+18/-0)
tests/regression/lp-1693042/task.yaml (+16/-0)
tests/regression/lp-1704860/snap-env-query.sh (+1/-0)
tests/regression/lp-1704860/task.yaml (+25/-0)
tests/regression/lp-1732555/task.yaml (+15/-0)
tests/regression/lp-1764977/task.yaml (+28/-0)
tests/snapd-state.md (+5/-0)
tests/unit/c-unit-tests-clang/task.yaml (+27/-0)
tests/unit/c-unit-tests-gcc/task.yaml (+27/-0)
tests/unit/gccgo/task.yaml (+22/-0)
tests/unit/go/task.yaml (+33/-0)
tests/unit/spread-shellcheck/can-fail (+150/-0)
tests/unit/spread-shellcheck/task.yaml (+15/-0)
tests/upgrade/basic/task.yaml (+110/-0)
tests/upgrade/snapd-xdg-open/task.yaml (+38/-0)
tests/util/benchmark.sh (+21/-0)
testutil/base.go (+51/-0)
testutil/checkers.go (+289/-0)
testutil/checkers_test.go (+378/-0)
testutil/dbustest.go (+72/-0)
testutil/exec.go (+149/-0)
testutil/exec_test.go (+68/-0)
testutil/lowlevel.go (+561/-0)
testutil/lowlevel_test.go (+749/-0)
timeout/timeout.go (+76/-0)
timeout/timeout_test.go (+65/-0)
timeutil/export_test.go (+34/-0)
timeutil/human.go (+80/-0)
timeutil/human_test.go (+93/-0)
timeutil/schedule.go (+762/-0)
timeutil/schedule_test.go (+1034/-0)
update-pot (+74/-0)
userd/autostart.go (+225/-0)
userd/autostart_test.go (+244/-0)
userd/export_test.go (+49/-0)
userd/helpers.go (+109/-0)
userd/helpers_test.go (+63/-0)
userd/launcher.go (+187/-0)
userd/launcher_test.go (+199/-0)
userd/settings.go (+226/-0)
userd/settings_test.go (+220/-0)
userd/ui/kdialog.go (+68/-0)
userd/ui/kdialog_test.go (+84/-0)
userd/ui/ui.go (+94/-0)
userd/ui/zenity.go (+55/-0)
userd/ui/zenity_test.go (+91/-0)
userd/userd.go (+98/-0)
vendor/github.com/coreos/go-systemd/LICENSE (+191/-0)
vendor/github.com/coreos/go-systemd/activation/files.go (+52/-0)
vendor/github.com/coreos/go-systemd/activation/listeners.go (+60/-0)
vendor/github.com/coreos/go-systemd/activation/packetconns.go (+37/-0)
vendor/github.com/godbus/dbus/CONTRIBUTING.md (+50/-0)
vendor/github.com/godbus/dbus/LICENSE (+25/-0)
vendor/github.com/godbus/dbus/MAINTAINERS (+3/-0)
vendor/github.com/godbus/dbus/README.markdown (+44/-0)
vendor/github.com/godbus/dbus/auth.go (+253/-0)
vendor/github.com/godbus/dbus/auth_external.go (+26/-0)
vendor/github.com/godbus/dbus/auth_sha1.go (+102/-0)
vendor/github.com/godbus/dbus/call.go (+36/-0)
vendor/github.com/godbus/dbus/conn.go (+683/-0)
vendor/github.com/godbus/dbus/conn_darwin.go (+33/-0)
vendor/github.com/godbus/dbus/conn_other.go (+42/-0)
vendor/github.com/godbus/dbus/dbus.go (+427/-0)
vendor/github.com/godbus/dbus/decoder.go (+228/-0)
vendor/github.com/godbus/dbus/default_handler.go (+283/-0)
vendor/github.com/godbus/dbus/doc.go (+69/-0)
vendor/github.com/godbus/dbus/encoder.go (+210/-0)
vendor/github.com/godbus/dbus/export.go (+413/-0)
vendor/github.com/godbus/dbus/homedir.go (+28/-0)
vendor/github.com/godbus/dbus/homedir_dynamic.go (+15/-0)
vendor/github.com/godbus/dbus/homedir_static.go (+45/-0)
vendor/github.com/godbus/dbus/introspect/call.go (+27/-0)
vendor/github.com/godbus/dbus/introspect/introspect.go (+86/-0)
vendor/github.com/godbus/dbus/introspect/introspectable.go (+76/-0)
vendor/github.com/godbus/dbus/message.go (+353/-0)
vendor/github.com/godbus/dbus/object.go (+136/-0)
vendor/github.com/godbus/dbus/server_interfaces.go (+89/-0)
vendor/github.com/godbus/dbus/sig.go (+259/-0)
vendor/github.com/godbus/dbus/transport_darwin.go (+6/-0)
vendor/github.com/godbus/dbus/transport_generic.go (+50/-0)
vendor/github.com/godbus/dbus/transport_tcp.go (+43/-0)
vendor/github.com/godbus/dbus/transport_unix.go (+196/-0)
vendor/github.com/godbus/dbus/transport_unixcred_dragonfly.go (+95/-0)
vendor/github.com/godbus/dbus/transport_unixcred_freebsd.go (+91/-0)
vendor/github.com/godbus/dbus/transport_unixcred_linux.go (+25/-0)
vendor/github.com/godbus/dbus/transport_unixcred_openbsd.go (+14/-0)
vendor/github.com/godbus/dbus/variant.go (+144/-0)
vendor/github.com/godbus/dbus/variant_lexer.go (+284/-0)
vendor/github.com/godbus/dbus/variant_parser.go (+817/-0)
vendor/github.com/gorilla/context/LICENSE (+27/-0)
vendor/github.com/gorilla/context/README.md (+7/-0)
vendor/github.com/gorilla/context/context.go (+143/-0)
vendor/github.com/gorilla/context/doc.go (+82/-0)
vendor/github.com/gorilla/mux/LICENSE (+27/-0)
vendor/github.com/gorilla/mux/README.md (+242/-0)
vendor/github.com/gorilla/mux/doc.go (+206/-0)
vendor/github.com/gorilla/mux/mux.go (+481/-0)
vendor/github.com/gorilla/mux/regexp.go (+312/-0)
vendor/github.com/gorilla/mux/route.go (+627/-0)
vendor/github.com/jessevdk/go-flags/LICENSE (+26/-0)
vendor/github.com/jessevdk/go-flags/README.md (+135/-0)
vendor/github.com/jessevdk/go-flags/arg.go (+27/-0)
vendor/github.com/jessevdk/go-flags/check_crosscompile.sh (+16/-0)
vendor/github.com/jessevdk/go-flags/closest.go (+59/-0)
vendor/github.com/jessevdk/go-flags/command.go (+455/-0)
vendor/github.com/jessevdk/go-flags/completion.go (+309/-0)
vendor/github.com/jessevdk/go-flags/convert.go (+348/-0)
vendor/github.com/jessevdk/go-flags/error.go (+134/-0)
vendor/github.com/jessevdk/go-flags/flags.go (+258/-0)
vendor/github.com/jessevdk/go-flags/group.go (+395/-0)
vendor/github.com/jessevdk/go-flags/help.go (+491/-0)
vendor/github.com/jessevdk/go-flags/ini.go (+597/-0)
vendor/github.com/jessevdk/go-flags/man.go (+205/-0)
vendor/github.com/jessevdk/go-flags/multitag.go (+140/-0)
vendor/github.com/jessevdk/go-flags/option.go (+461/-0)
vendor/github.com/jessevdk/go-flags/optstyle_other.go (+67/-0)
vendor/github.com/jessevdk/go-flags/optstyle_windows.go (+108/-0)
vendor/github.com/jessevdk/go-flags/parser.go (+700/-0)
vendor/github.com/jessevdk/go-flags/termsize.go (+28/-0)
vendor/github.com/jessevdk/go-flags/termsize_linux.go (+7/-0)
vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go (+7/-0)
vendor/github.com/jessevdk/go-flags/termsize_other.go (+7/-0)
vendor/github.com/jessevdk/go-flags/termsize_unix.go (+7/-0)
vendor/github.com/mvo5/goconfigparser/COPYING (+19/-0)
vendor/github.com/mvo5/goconfigparser/README.md (+18/-0)
vendor/github.com/mvo5/goconfigparser/configparser.go (+181/-0)
vendor/github.com/mvo5/libseccomp-golang/CHANGELOG (+6/-0)
vendor/github.com/mvo5/libseccomp-golang/LICENSE (+22/-0)
vendor/github.com/mvo5/libseccomp-golang/Makefile (+26/-0)
vendor/github.com/mvo5/libseccomp-golang/README (+51/-0)
vendor/github.com/mvo5/libseccomp-golang/SUBMITTING_PATCHES (+112/-0)
vendor/github.com/mvo5/libseccomp-golang/seccomp.go (+872/-0)
vendor/github.com/mvo5/libseccomp-golang/seccomp_internal.go (+549/-0)
vendor/github.com/ojii/gettext.go/LICENSE (+24/-0)
vendor/github.com/ojii/gettext.go/README.md (+33/-0)
vendor/github.com/ojii/gettext.go/gettext.go (+77/-0)
vendor/github.com/ojii/gettext.go/mofile.go (+235/-0)
vendor/github.com/ojii/gettext.go/pluralforms/compiler.go (+427/-0)
vendor/github.com/ojii/gettext.go/pluralforms/expression.go (+39/-0)
vendor/github.com/ojii/gettext.go/pluralforms/genfixture.py (+35/-0)
vendor/github.com/ojii/gettext.go/pluralforms/math.go (+13/-0)
vendor/github.com/ojii/gettext.go/pluralforms/tests.go (+104/-0)
vendor/github.com/ojii/gettext.go/test_utils.go (+10/-0)
vendor/github.com/snapcore/bolt/LICENSE (+20/-0)
vendor/github.com/snapcore/bolt/Makefile (+18/-0)
vendor/github.com/snapcore/bolt/README.md (+935/-0)
vendor/github.com/snapcore/bolt/appveyor.yml (+18/-0)
vendor/github.com/snapcore/bolt/bolt_386.go (+10/-0)
vendor/github.com/snapcore/bolt/bolt_amd64.go (+10/-0)
vendor/github.com/snapcore/bolt/bolt_arm.go (+28/-0)
vendor/github.com/snapcore/bolt/bolt_arm64.go (+12/-0)
vendor/github.com/snapcore/bolt/bolt_linux.go (+10/-0)
vendor/github.com/snapcore/bolt/bolt_openbsd.go (+27/-0)
vendor/github.com/snapcore/bolt/bolt_ppc.go (+12/-0)
vendor/github.com/snapcore/bolt/bolt_ppc64.go (+12/-0)
vendor/github.com/snapcore/bolt/bolt_ppc64le.go (+12/-0)
vendor/github.com/snapcore/bolt/bolt_s390x.go (+12/-0)
vendor/github.com/snapcore/bolt/bolt_unix.go (+89/-0)
vendor/github.com/snapcore/bolt/bolt_unix_solaris.go (+90/-0)
vendor/github.com/snapcore/bolt/bolt_windows.go (+144/-0)
vendor/github.com/snapcore/bolt/boltsync_unix.go (+8/-0)
vendor/github.com/snapcore/bolt/bucket.go (+777/-0)
vendor/github.com/snapcore/bolt/cursor.go (+400/-0)
vendor/github.com/snapcore/bolt/db.go (+1037/-0)
vendor/github.com/snapcore/bolt/doc.go (+44/-0)
vendor/github.com/snapcore/bolt/errors.go (+71/-0)
vendor/github.com/snapcore/bolt/freelist.go (+252/-0)
vendor/github.com/snapcore/bolt/node.go (+604/-0)
vendor/github.com/snapcore/bolt/page.go (+197/-0)
vendor/github.com/snapcore/bolt/tx.go (+684/-0)
vendor/github.com/snapcore/squashfuse/dummy.go (+6/-0)
vendor/github.com/snapcore/squashfuse/src/CONFIGURATION (+19/-0)
vendor/github.com/snapcore/squashfuse/src/LICENSE (+31/-0)
vendor/github.com/snapcore/squashfuse/src/Makefile.am (+76/-0)
vendor/github.com/snapcore/squashfuse/src/NEWS (+19/-0)
vendor/github.com/snapcore/squashfuse/src/PLATFORMS (+114/-0)
vendor/github.com/snapcore/squashfuse/src/README (+271/-0)
vendor/github.com/snapcore/squashfuse/src/TODO (+69/-0)
vendor/github.com/snapcore/squashfuse/src/autogen.sh (+25/-0)
vendor/github.com/snapcore/squashfuse/src/cache.c (+91/-0)
vendor/github.com/snapcore/squashfuse/src/cache.h (+66/-0)
vendor/github.com/snapcore/squashfuse/src/common.h (+69/-0)
vendor/github.com/snapcore/squashfuse/src/configure.ac (+73/-0)
vendor/github.com/snapcore/squashfuse/src/decompress.c (+163/-0)
vendor/github.com/snapcore/squashfuse/src/decompress.h (+46/-0)
vendor/github.com/snapcore/squashfuse/src/dir.c (+316/-0)
vendor/github.com/snapcore/squashfuse/src/dir.h (+90/-0)
vendor/github.com/snapcore/squashfuse/src/extract.c (+179/-0)
vendor/github.com/snapcore/squashfuse/src/file.c (+321/-0)
vendor/github.com/snapcore/squashfuse/src/file.h (+82/-0)
vendor/github.com/snapcore/squashfuse/src/fs.c (+446/-0)
vendor/github.com/snapcore/squashfuse/src/fs.h (+135/-0)
vendor/github.com/snapcore/squashfuse/src/fuseprivate.c (+128/-0)
vendor/github.com/snapcore/squashfuse/src/fuseprivate.h (+55/-0)
vendor/github.com/snapcore/squashfuse/src/gen_swap.sh (+36/-0)
vendor/github.com/snapcore/squashfuse/src/hash.c (+131/-0)
vendor/github.com/snapcore/squashfuse/src/hash.h (+63/-0)
vendor/github.com/snapcore/squashfuse/src/hl.c (+315/-0)
vendor/github.com/snapcore/squashfuse/src/ll.c (+473/-0)
vendor/github.com/snapcore/squashfuse/src/ll.h (+70/-0)
vendor/github.com/snapcore/squashfuse/src/ll_inode.c (+391/-0)
vendor/github.com/snapcore/squashfuse/src/ls.c (+75/-0)
vendor/github.com/snapcore/squashfuse/src/m4/squashfuse.m4 (+99/-0)
vendor/github.com/snapcore/squashfuse/src/m4/squashfuse_c.m4 (+70/-0)
vendor/github.com/snapcore/squashfuse/src/m4/squashfuse_decompress.m4 (+66/-0)
vendor/github.com/snapcore/squashfuse/src/m4/squashfuse_fuse.m4 (+288/-0)
vendor/github.com/snapcore/squashfuse/src/m4/squashfuse_posix.m4 (+130/-0)
vendor/github.com/snapcore/squashfuse/src/nonstd-daemon.c (+40/-0)
vendor/github.com/snapcore/squashfuse/src/nonstd-enoattr.c (+42/-0)
vendor/github.com/snapcore/squashfuse/src/nonstd-internal.h (+44/-0)
vendor/github.com/snapcore/squashfuse/src/nonstd-makedev.c (+49/-0)
vendor/github.com/snapcore/squashfuse/src/nonstd-pread.c (+51/-0)
vendor/github.com/snapcore/squashfuse/src/nonstd-stat.c (+62/-0)
vendor/github.com/snapcore/squashfuse/src/nonstd.h (+38/-0)
vendor/github.com/snapcore/squashfuse/src/squashfs_fs.h (+322/-0)
vendor/github.com/snapcore/squashfuse/src/squashfuse.1 (+69/-0)
vendor/github.com/snapcore/squashfuse/src/squashfuse.h (+35/-0)
vendor/github.com/snapcore/squashfuse/src/stack.c (+130/-0)
vendor/github.com/snapcore/squashfuse/src/stack.h (+54/-0)
vendor/github.com/snapcore/squashfuse/src/swap.c (+53/-0)
vendor/github.com/snapcore/squashfuse/src/swap.h (+41/-0)
vendor/github.com/snapcore/squashfuse/src/table.c (+81/-0)
vendor/github.com/snapcore/squashfuse/src/table.h (+41/-0)
vendor/github.com/snapcore/squashfuse/src/traverse.c (+322/-0)
vendor/github.com/snapcore/squashfuse/src/traverse.h (+69/-0)
vendor/github.com/snapcore/squashfuse/src/util.c (+125/-0)
vendor/github.com/snapcore/squashfuse/src/util.h (+41/-0)
vendor/github.com/snapcore/squashfuse/src/win/config.h (+1/-0)
vendor/github.com/snapcore/squashfuse/src/win/squashfuse_ls.sln (+22/-0)
vendor/github.com/snapcore/squashfuse/src/win/squashfuse_ls.vcxproj (+127/-0)
vendor/github.com/snapcore/squashfuse/src/win/squashfuse_ls.vcxproj.filters (+143/-0)
vendor/github.com/snapcore/squashfuse/src/win/tinfl.c (+592/-0)
vendor/github.com/snapcore/squashfuse/src/win/win32.h (+46/-0)
vendor/github.com/snapcore/squashfuse/src/win/win_decompress.c.inc (+51/-0)
vendor/github.com/snapcore/squashfuse/src/xattr.c (+273/-0)
vendor/github.com/snapcore/squashfuse/src/xattr.h (+74/-0)
vendor/golang.org/x/crypto/LICENSE (+27/-0)
vendor/golang.org/x/crypto/PATENTS (+22/-0)
vendor/golang.org/x/crypto/cast5/cast5.go (+526/-0)
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go (+149/-0)
vendor/golang.org/x/crypto/openpgp/armor/armor.go (+219/-0)
vendor/golang.org/x/crypto/openpgp/armor/encode.go (+160/-0)
vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go (+122/-0)
vendor/golang.org/x/crypto/openpgp/errors/errors.go (+72/-0)
vendor/golang.org/x/crypto/openpgp/packet/compressed.go (+123/-0)
vendor/golang.org/x/crypto/openpgp/packet/config.go (+91/-0)
vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go (+199/-0)
vendor/golang.org/x/crypto/openpgp/packet/literal.go (+89/-0)
vendor/golang.org/x/crypto/openpgp/packet/ocfb.go (+143/-0)
vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go (+73/-0)
vendor/golang.org/x/crypto/openpgp/packet/opaque.go (+162/-0)
vendor/golang.org/x/crypto/openpgp/packet/packet.go (+537/-0)
vendor/golang.org/x/crypto/openpgp/packet/private_key.go (+380/-0)
vendor/golang.org/x/crypto/openpgp/packet/public_key.go (+748/-0)
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go (+279/-0)
vendor/golang.org/x/crypto/openpgp/packet/reader.go (+76/-0)
vendor/golang.org/x/crypto/openpgp/packet/signature.go (+731/-0)
vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go (+146/-0)
vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go (+155/-0)
vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go (+290/-0)
vendor/golang.org/x/crypto/openpgp/packet/userattribute.go (+91/-0)
vendor/golang.org/x/crypto/openpgp/packet/userid.go (+160/-0)
vendor/golang.org/x/crypto/openpgp/s2k/s2k.go (+273/-0)
vendor/golang.org/x/crypto/poly1305/poly1305.go (+33/-0)
vendor/golang.org/x/crypto/poly1305/sum_amd64.go (+22/-0)
vendor/golang.org/x/crypto/poly1305/sum_amd64.s (+125/-0)
vendor/golang.org/x/crypto/poly1305/sum_arm.go (+22/-0)
vendor/golang.org/x/crypto/poly1305/sum_arm.s (+427/-0)
vendor/golang.org/x/crypto/poly1305/sum_ref.go (+141/-0)
vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go (+144/-0)
vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s (+889/-0)
vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go (+199/-0)
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go (+23/-0)
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go (+234/-0)
vendor/golang.org/x/crypto/sha3/doc.go (+66/-0)
vendor/golang.org/x/crypto/sha3/hashes.go (+65/-0)
vendor/golang.org/x/crypto/sha3/keccakf.go (+412/-0)
vendor/golang.org/x/crypto/sha3/keccakf_amd64.go (+13/-0)
vendor/golang.org/x/crypto/sha3/keccakf_amd64.s (+390/-0)
vendor/golang.org/x/crypto/sha3/register.go (+18/-0)
vendor/golang.org/x/crypto/sha3/sha3.go (+193/-0)
vendor/golang.org/x/crypto/sha3/shake.go (+60/-0)
vendor/golang.org/x/crypto/sha3/xor.go (+16/-0)
vendor/golang.org/x/crypto/sha3/xor_generic.go (+28/-0)
vendor/golang.org/x/crypto/sha3/xor_unaligned.go (+58/-0)
vendor/golang.org/x/crypto/ssh/terminal/terminal.go (+892/-0)
vendor/golang.org/x/crypto/ssh/terminal/util.go (+133/-0)
vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go (+12/-0)
vendor/golang.org/x/crypto/ssh/terminal/util_linux.go (+11/-0)
vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go (+58/-0)
vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go (+73/-0)
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go (+174/-0)
vendor/golang.org/x/net/LICENSE (+27/-0)
vendor/golang.org/x/net/PATENTS (+22/-0)
vendor/golang.org/x/net/context/context.go (+156/-0)
vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go (+74/-0)
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go (+147/-0)
vendor/golang.org/x/net/context/go17.go (+72/-0)
vendor/golang.org/x/net/context/pre_go17.go (+300/-0)
vendor/gopkg.in/check.v1/LICENSE (+25/-0)
vendor/gopkg.in/check.v1/README.md (+20/-0)
vendor/gopkg.in/check.v1/TODO (+2/-0)
vendor/gopkg.in/check.v1/benchmark.go (+187/-0)
vendor/gopkg.in/check.v1/check.go (+873/-0)
vendor/gopkg.in/check.v1/checkers.go (+458/-0)
vendor/gopkg.in/check.v1/helpers.go (+231/-0)
vendor/gopkg.in/check.v1/printer.go (+168/-0)
vendor/gopkg.in/check.v1/reporter.go (+88/-0)
vendor/gopkg.in/check.v1/run.go (+175/-0)
vendor/gopkg.in/macaroon.v1/LICENSE (+26/-0)
vendor/gopkg.in/macaroon.v1/README.md (+159/-0)
vendor/gopkg.in/macaroon.v1/TODO (+4/-0)
vendor/gopkg.in/macaroon.v1/crypto.go (+91/-0)
vendor/gopkg.in/macaroon.v1/macaroon.go (+292/-0)
vendor/gopkg.in/macaroon.v1/marshal.go (+259/-0)
vendor/gopkg.in/macaroon.v1/packet.go (+156/-0)
vendor/gopkg.in/mgo.v2/LICENSE (+25/-0)
vendor/gopkg.in/mgo.v2/bson/LICENSE (+25/-0)
vendor/gopkg.in/mgo.v2/bson/bson.go (+734/-0)
vendor/gopkg.in/mgo.v2/bson/decimal.go (+310/-0)
vendor/gopkg.in/mgo.v2/bson/decode.go (+849/-0)
vendor/gopkg.in/mgo.v2/bson/encode.go (+514/-0)
vendor/gopkg.in/mgo.v2/bson/json.go (+380/-0)
vendor/gopkg.in/mgo.v2/internal/json/LICENSE (+27/-0)
vendor/gopkg.in/mgo.v2/internal/json/decode.go (+1685/-0)
vendor/gopkg.in/mgo.v2/internal/json/encode.go (+1256/-0)
vendor/gopkg.in/mgo.v2/internal/json/extension.go (+95/-0)
vendor/gopkg.in/mgo.v2/internal/json/fold.go (+143/-0)
vendor/gopkg.in/mgo.v2/internal/json/indent.go (+141/-0)
vendor/gopkg.in/mgo.v2/internal/json/scanner.go (+697/-0)
vendor/gopkg.in/mgo.v2/internal/json/stream.go (+510/-0)
vendor/gopkg.in/mgo.v2/internal/json/tags.go (+44/-0)
vendor/gopkg.in/retry.v1/LICENSE (+186/-0)
vendor/gopkg.in/retry.v1/README.md (+202/-0)
vendor/gopkg.in/retry.v1/clock.go (+23/-0)
vendor/gopkg.in/retry.v1/exp.go (+50/-0)
vendor/gopkg.in/retry.v1/regular.go (+65/-0)
vendor/gopkg.in/retry.v1/retry.go (+156/-0)
vendor/gopkg.in/retry.v1/strategy.go (+60/-0)
vendor/gopkg.in/tomb.v2/LICENSE (+29/-0)
vendor/gopkg.in/tomb.v2/README.md (+4/-0)
vendor/gopkg.in/tomb.v2/context.go (+74/-0)
vendor/gopkg.in/tomb.v2/context16.go (+74/-0)
vendor/gopkg.in/tomb.v2/tomb.go (+237/-0)
vendor/gopkg.in/tylerb/graceful.v1/LICENSE (+21/-0)
vendor/gopkg.in/tylerb/graceful.v1/README.md (+152/-0)
vendor/gopkg.in/tylerb/graceful.v1/graceful.go (+487/-0)
vendor/gopkg.in/tylerb/graceful.v1/keepalive_listener.go (+32/-0)
vendor/gopkg.in/tylerb/graceful.v1/limit_listen.go (+77/-0)
vendor/gopkg.in/yaml.v2/LICENSE (+201/-0)
vendor/gopkg.in/yaml.v2/LICENSE.libyaml (+31/-0)
vendor/gopkg.in/yaml.v2/NOTICE (+13/-0)
vendor/gopkg.in/yaml.v2/README.md (+133/-0)
vendor/gopkg.in/yaml.v2/apic.go (+739/-0)
vendor/gopkg.in/yaml.v2/decode.go (+775/-0)
vendor/gopkg.in/yaml.v2/emitterc.go (+1685/-0)
vendor/gopkg.in/yaml.v2/encode.go (+356/-0)
vendor/gopkg.in/yaml.v2/go.mod (+5/-0)
vendor/gopkg.in/yaml.v2/parserc.go (+1095/-0)
vendor/gopkg.in/yaml.v2/readerc.go (+412/-0)
vendor/gopkg.in/yaml.v2/resolve.go (+258/-0)
vendor/gopkg.in/yaml.v2/scannerc.go (+2696/-0)
vendor/gopkg.in/yaml.v2/sorter.go (+113/-0)
vendor/gopkg.in/yaml.v2/writerc.go (+26/-0)
vendor/gopkg.in/yaml.v2/yaml.go (+466/-0)
vendor/gopkg.in/yaml.v2/yamlh.go (+738/-0)
vendor/gopkg.in/yaml.v2/yamlprivateh.go (+173/-0)
vendor/vendor.json (+211/-0)
wrappers/binaries.go (+91/-0)
wrappers/binaries_test.go (+151/-0)
wrappers/core18.go (+183/-0)
wrappers/core18_test.go (+119/-0)
wrappers/desktop.go (+259/-0)
wrappers/desktop_test.go (+471/-0)
wrappers/export_test.go (+47/-0)
wrappers/services.go (+701/-0)
wrappers/services_gen_test.go (+585/-0)
wrappers/services_test.go (+919/-0)
x11/xauth.go (+151/-0)
x11/xauth_test.go (+74/-0)
xdgopenproxy/export_test.go (+22/-0)
xdgopenproxy/xdgopenproxy.go (+63/-0)
xdgopenproxy/xdgopenproxy_test.go (+159/-0)
Reviewer Review Type Date Requested Status
Scott Moser (community) Disapprove
Canonical Server Pending
Michael Vogt Pending
Review via email: mp+354728@code.launchpad.net

Description of the change

Do not install snapd-env-generator

This can be added back when a suitable fix is found.

LP: #1791691.

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

Something is confusing launchpad. Possibly debian being a symlink.

$ git diff pkg/import/2.35.1+18.10..50e1b6c | pastebinit
http://paste.ubuntu.com/p/rdtghzRfdM/

Revision history for this message
Scott Moser (smoser) wrote :

The minimal change here does seem like it would fix the problem.
It would be acceptable because to my knowledge nothing in snapd currently relies on PATH getting /snapd/bin in it. Prior to this upload systemd units would not have that component in PATH.

That said, the plan right now is for snapd team to upload a fix tomorrow based on
 https://github.com/snapcore/snapd/pull/5808

review: Disapprove

Unmerged commits

50e1b6c... by Scott Moser

update changelog.

32cc154... by Scott Moser

Do not install snapd-env-generator

This can be added back when a suitable fix is found.

LP: #1791691.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/packaging/ubuntu-16.04/changelog b/packaging/ubuntu-16.04/changelog
2index e2041f1..23d1753 100644
3--- a/packaging/ubuntu-16.04/changelog
4+++ b/packaging/ubuntu-16.04/changelog
5@@ -1,3 +1,10 @@
6+snapd (2.35.1+18.10.1) UNRELEASED; urgency=medium
7+
8+ * Do not install snapd-env-generator (LP: #1791691).
9+ This can be added back when a suitable fix is found.
10+
11+ -- Scott Moser <smoser@ubuntu.com> Tue, 11 Sep 2018 16:00:13 -0400
12+
13 snapd (2.35.1+18.10) cosmic; urgency=medium
14
15 * New upstream release, LP: #1786438
16diff --git a/packaging/ubuntu-16.04/snapd.install b/packaging/ubuntu-16.04/snapd.install
17index d37e3da..f0a1865 100644
18--- a/packaging/ubuntu-16.04/snapd.install
19+++ b/packaging/ubuntu-16.04/snapd.install
20@@ -39,6 +39,3 @@ usr/lib/snapd/snap-gdb-shim
21 # install squashfuse as snapfuse to ensure it is available in e.g. lxd
22 vendor/github.com/snapcore/squashfuse/src/snapfuse usr/bin
23
24-# use "usr/lib" here because apparently systemd looks only there
25-usr/lib/systemd/system-environment-generators
26-
27diff --git a/tests/lib/changes.sh b/tests/lib/changes.sh
28new file mode 100755
29index 0000000..010bcfa
30--- /dev/null
31+++ b/tests/lib/changes.sh
32@@ -0,0 +1,8 @@
33+#!/bin/bash
34+
35+change_id() {
36+ # takes <summary pattern> [<status>]
37+ local SUMMARY_PAT=$1
38+ local STATUS=${2:-}
39+ snap changes|grep -o -P "^\\d+(?= *${STATUS}.*${SUMMARY_PAT}.*)"
40+}
41diff --git a/tests/lib/dbus.sh b/tests/lib/dbus.sh
42new file mode 100755
43index 0000000..5a3b95d
44--- /dev/null
45+++ b/tests/lib/dbus.sh
46@@ -0,0 +1,35 @@
47+#!/bin/bash
48+
49+start_dbus_unit(){
50+ local executable="$1"
51+
52+ dbus-launch > dbus.env
53+ # shellcheck disable=SC2046
54+ export $(cat dbus.env)
55+ if [[ "$SPREAD_SYSTEM" == ubuntu-14.04-* ]]; then
56+ cat <<EOF > /etc/init/dbus-provider.conf
57+env DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS"
58+env DBUS_SESSION_BUS_PID="$DBUS_SESSION_BUS_PID"
59+script
60+ $executable
61+end script
62+EOF
63+ initctl reload-configuration
64+ start dbus-provider
65+ else
66+ systemd-run --unit dbus-provider \
67+ --setenv=DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
68+ --setenv=DBUS_SESSION_BUS_PID="$DBUS_SESSION_BUS_PID" \
69+ "$executable"
70+ fi
71+}
72+
73+stop_dbus_unit(){
74+ rm -f dbus.env
75+ if [[ "$SPREAD_SYSTEM" == ubuntu-14.04-* ]]; then
76+ stop dbus-provider
77+ rm -f /etc/init/dbus-provider.conf
78+ else
79+ systemctl stop dbus-provider || true
80+ fi
81+}
82diff --git a/tests/lib/dirs.sh b/tests/lib/dirs.sh
83new file mode 100644
84index 0000000..e83c053
85--- /dev/null
86+++ b/tests/lib/dirs.sh
87@@ -0,0 +1,23 @@
88+#!/bin/bash
89+
90+export SNAP_MOUNT_DIR=/snap
91+export LIBEXECDIR=/usr/lib
92+export MEDIA_DIR=/media
93+
94+case "$SPREAD_SYSTEM" in
95+ fedora-*|amazon-*)
96+ export SNAP_MOUNT_DIR=/var/lib/snapd/snap
97+ export LIBEXECDIR=/usr/libexec
98+ export MEDIA_DIR=/run/media
99+ ;;
100+ arch-*)
101+ export SNAP_MOUNT_DIR=/var/lib/snapd/snap
102+ export MEDIA_DIR=/run/media
103+ ;;
104+ opensuse-*)
105+ export SNAP_MOUNT_DIR=/snap
106+ export MEDIA_DIR=/run/media
107+ ;;
108+ *)
109+ ;;
110+esac
111diff --git a/tests/lib/external/prepare-ssh.sh b/tests/lib/external/prepare-ssh.sh
112new file mode 100755
113index 0000000..6a351b6
114--- /dev/null
115+++ b/tests/lib/external/prepare-ssh.sh
116@@ -0,0 +1,15 @@
117+#!/bin/sh
118+set -ex
119+
120+INSTANCE_IP="${1:-localhost}"
121+INSTANCE_PORT="${2:-8022}"
122+USER="${3:-$(whoami)}"
123+
124+execute_remote(){
125+ # shellcheck disable=SC2029
126+ ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p "$INSTANCE_PORT" "$USER@$INSTANCE_IP" "$@"
127+}
128+
129+execute_remote "sudo adduser --extrausers --quiet --disabled-password --gecos '' test"
130+execute_remote "echo test:ubuntu | sudo chpasswd"
131+execute_remote "echo 'test ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/create-user-test"
132diff --git a/tests/lib/fakedevicesvc/main.go b/tests/lib/fakedevicesvc/main.go
133new file mode 100644
134index 0000000..e35d64c
135--- /dev/null
136+++ b/tests/lib/fakedevicesvc/main.go
137@@ -0,0 +1,135 @@
138+// -*- Mode: Go; indent-tabs-mode: t -*-
139+
140+/*
141+ * Copyright (C) 2016 Canonical Ltd
142+ *
143+ * This program is free software: you can redistribute it and/or modify
144+ * it under the terms of the GNU General Public License version 3 as
145+ * published by the Free Software Foundation.
146+ *
147+ * This program is distributed in the hope that it will be useful,
148+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
149+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
150+ * GNU General Public License for more details.
151+ *
152+ * You should have received a copy of the GNU General Public License
153+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
154+ *
155+ */
156+
157+package main
158+
159+import (
160+ "fmt"
161+ "io"
162+ "io/ioutil"
163+ "net"
164+ "net/http"
165+ "os"
166+ "os/signal"
167+ "syscall"
168+ "time"
169+
170+ "github.com/snapcore/snapd/asserts"
171+ "github.com/snapcore/snapd/asserts/assertstest"
172+)
173+
174+var devPrivKey, _ = assertstest.ReadPrivKey(assertstest.DevKey)
175+
176+func main() {
177+ if len(os.Args) < 2 {
178+ fmt.Fprintf(os.Stderr, "no listening address arg\n")
179+ os.Exit(1)
180+ }
181+
182+ l, err := net.Listen("tcp", os.Args[1])
183+ if err != nil {
184+ fmt.Fprintf(os.Stderr, "cannot listen: %v\n", err)
185+ os.Exit(1)
186+ }
187+
188+ s := &http.Server{Handler: http.HandlerFunc(handle)}
189+ go s.Serve(l)
190+
191+ ch := make(chan os.Signal)
192+ signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
193+ <-ch
194+
195+ l.Close()
196+}
197+
198+func internalError(w http.ResponseWriter, msg string, a ...interface{}) {
199+ http.Error(w, fmt.Sprintf(msg, a...), 500)
200+}
201+
202+func badRequestError(w http.ResponseWriter, msg string, a ...interface{}) {
203+ http.Error(w, fmt.Sprintf(msg, a...), 400)
204+}
205+
206+func handle(w http.ResponseWriter, r *http.Request) {
207+ switch r.URL.Path {
208+ case "/request-id":
209+ w.WriteHeader(200)
210+ io.WriteString(w, fmt.Sprintf(`{"request-id": "REQ-ID"}`))
211+ case "/serial":
212+ db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{})
213+ if err != nil {
214+ internalError(w, "cannot open signing db: %v", err)
215+ return
216+ }
217+ err = db.ImportKey(devPrivKey)
218+ if err != nil {
219+ internalError(w, "cannot import signing key: %v", err)
220+ return
221+ }
222+
223+ b, err := ioutil.ReadAll(r.Body)
224+ if err != nil {
225+ internalError(w, "cannot read request: %v", err)
226+ return
227+ }
228+
229+ a, err := asserts.Decode(b)
230+ if err != nil {
231+ badRequestError(w, "cannot decode request: %v", err)
232+ return
233+ }
234+
235+ serialReq, ok := a.(*asserts.SerialRequest)
236+ if !ok {
237+ badRequestError(w, "request is not a serial-request")
238+ return
239+
240+ }
241+
242+ err = asserts.SignatureCheck(serialReq, serialReq.DeviceKey())
243+ if err != nil {
244+ badRequestError(w, "bad serial-request: %v", err)
245+ return
246+ }
247+
248+ serialStr := "7777"
249+ if r.Header.Get("X-Use-Proposed") == "yes" {
250+ // use proposed serial
251+ serialStr = serialReq.Serial()
252+ }
253+
254+ serial, err := db.Sign(asserts.SerialType, map[string]interface{}{
255+ "authority-id": "developer1",
256+ "brand-id": "developer1",
257+ "model": serialReq.Model(),
258+ "serial": serialStr,
259+ "device-key": serialReq.HeaderString("device-key"),
260+ "device-key-sha3-384": serialReq.SignKeyID(),
261+ "timestamp": time.Now().Format(time.RFC3339),
262+ }, serialReq.Body(), devPrivKey.PublicKey().ID())
263+ if err != nil {
264+ internalError(w, "cannot sign serial: %v", err)
265+ return
266+ }
267+
268+ w.Header().Set("Content-Type", asserts.MediaType)
269+ w.WriteHeader(200)
270+ w.Write(asserts.Encode(serial))
271+ }
272+}
273diff --git a/tests/lib/fakestore/cmd/fakestore/cmd_make_refreshable.go b/tests/lib/fakestore/cmd/fakestore/cmd_make_refreshable.go
274new file mode 100644
275index 0000000..41a64ee
276--- /dev/null
277+++ b/tests/lib/fakestore/cmd/fakestore/cmd_make_refreshable.go
278@@ -0,0 +1,39 @@
279+// -*- Mode: Go; indent-tabs-mode: t -*-
280+
281+/*
282+ * Copyright (C) 2017 Canonical Ltd
283+ *
284+ * This program is free software: you can redistribute it and/or modify
285+ * it under the terms of the GNU General Public License version 3 as
286+ * published by the Free Software Foundation.
287+ *
288+ * This program is distributed in the hope that it will be useful,
289+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
290+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
291+ * GNU General Public License for more details.
292+ *
293+ * You should have received a copy of the GNU General Public License
294+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
295+ *
296+ */
297+
298+package main
299+
300+import (
301+ "github.com/snapcore/snapd/tests/lib/fakestore/refresh"
302+)
303+
304+type cmdMakeRefreshable struct {
305+ TopDir string `long:"dir" description:"Directory to be used by the store to keep and serve snaps, <dir>/asserts is used for assertions"`
306+}
307+
308+func (x *cmdMakeRefreshable) Execute(args []string) error {
309+ // setup fake new revisions of snaps for refresh
310+ return refresh.MakeFakeRefreshForSnaps(args, x.TopDir)
311+}
312+
313+var shortMakeRefreshableHelp = "Makes new versions of the given snaps"
314+
315+func init() {
316+ parser.AddCommand("make-refreshable", shortMakeRefreshableHelp, "", &cmdMakeRefreshable{})
317+}
318diff --git a/tests/lib/fakestore/cmd/fakestore/cmd_new_snap_decl.go b/tests/lib/fakestore/cmd/fakestore/cmd_new_snap_decl.go
319new file mode 100644
320index 0000000..eedbb4b
321--- /dev/null
322+++ b/tests/lib/fakestore/cmd/fakestore/cmd_new_snap_decl.go
323@@ -0,0 +1,63 @@
324+// -*- Mode: Go; indent-tabs-mode: t -*-
325+
326+/*
327+ * Copyright (C) 2017 Canonical Ltd
328+ *
329+ * This program is free software: you can redistribute it and/or modify
330+ * it under the terms of the GNU General Public License version 3 as
331+ * published by the Free Software Foundation.
332+ *
333+ * This program is distributed in the hope that it will be useful,
334+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
335+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
336+ * GNU General Public License for more details.
337+ *
338+ * You should have received a copy of the GNU General Public License
339+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
340+ *
341+ */
342+
343+package main
344+
345+import (
346+ "encoding/json"
347+ "fmt"
348+ "io/ioutil"
349+
350+ "github.com/snapcore/snapd/tests/lib/fakestore/refresh"
351+)
352+
353+type cmdNewSnapDeclaration struct {
354+ Positional struct {
355+ Snap string
356+ } `positional-args:"yes"`
357+
358+ TopDir string `long:"dir" description:"Directory to be used by the store to keep and serve snaps, <dir>/asserts is used for assertions"`
359+ SnapDeclJsonPath string `long:"snap-decl-json" description:"Path to a json encoded snap declaration"`
360+}
361+
362+func (x *cmdNewSnapDeclaration) Execute(args []string) error {
363+ headers := map[string]interface{}{}
364+ if x.SnapDeclJsonPath != "" {
365+ content, err := ioutil.ReadFile(x.SnapDeclJsonPath)
366+ if err != nil {
367+ return err
368+ }
369+ if err := json.Unmarshal(content, &headers); err != nil {
370+ return err
371+ }
372+ }
373+
374+ p, err := refresh.NewSnapDeclaration(x.TopDir, x.Positional.Snap, headers)
375+ if err != nil {
376+ return err
377+ }
378+ fmt.Println(p)
379+ return nil
380+}
381+
382+var shortNewSnapDeclarationHelp = "Make new snap declaration"
383+
384+func init() {
385+ parser.AddCommand("new-snap-declaration", shortNewSnapDeclarationHelp, "", &cmdNewSnapDeclaration{})
386+}
387diff --git a/tests/lib/fakestore/cmd/fakestore/cmd_new_snap_rev.go b/tests/lib/fakestore/cmd/fakestore/cmd_new_snap_rev.go
388new file mode 100644
389index 0000000..e011037
390--- /dev/null
391+++ b/tests/lib/fakestore/cmd/fakestore/cmd_new_snap_rev.go
392@@ -0,0 +1,63 @@
393+// -*- Mode: Go; indent-tabs-mode: t -*-
394+
395+/*
396+ * Copyright (C) 2017 Canonical Ltd
397+ *
398+ * This program is free software: you can redistribute it and/or modify
399+ * it under the terms of the GNU General Public License version 3 as
400+ * published by the Free Software Foundation.
401+ *
402+ * This program is distributed in the hope that it will be useful,
403+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
404+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
405+ * GNU General Public License for more details.
406+ *
407+ * You should have received a copy of the GNU General Public License
408+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
409+ *
410+ */
411+
412+package main
413+
414+import (
415+ "encoding/json"
416+ "fmt"
417+ "io/ioutil"
418+
419+ "github.com/snapcore/snapd/tests/lib/fakestore/refresh"
420+)
421+
422+type cmdNewSnapRevision struct {
423+ Positional struct {
424+ Snap string
425+ } `positional-args:"yes"`
426+
427+ TopDir string `long:"dir" description:"Directory to be used by the store to keep and serve snaps, <dir>/asserts is used for assertions"`
428+ SnapRevJsonPath string `long:"snap-rev-json" description:"Path to a json encoded snap revision"`
429+}
430+
431+func (x *cmdNewSnapRevision) Execute(args []string) error {
432+ headers := map[string]interface{}{}
433+ if x.SnapRevJsonPath != "" {
434+ content, err := ioutil.ReadFile(x.SnapRevJsonPath)
435+ if err != nil {
436+ return err
437+ }
438+ if err := json.Unmarshal(content, &headers); err != nil {
439+ return err
440+ }
441+ }
442+
443+ p, err := refresh.NewSnapRevision(x.TopDir, x.Positional.Snap, headers)
444+ if err != nil {
445+ return err
446+ }
447+ fmt.Println(p)
448+ return nil
449+}
450+
451+var shortNewSnapRevisionHelp = "Make new snap revision"
452+
453+func init() {
454+ parser.AddCommand("new-snap-revision", shortNewSnapRevisionHelp, "", &cmdNewSnapRevision{})
455+}
456diff --git a/tests/lib/fakestore/cmd/fakestore/cmd_run.go b/tests/lib/fakestore/cmd/fakestore/cmd_run.go
457new file mode 100644
458index 0000000..405561a
459--- /dev/null
460+++ b/tests/lib/fakestore/cmd/fakestore/cmd_run.go
461@@ -0,0 +1,70 @@
462+// -*- Mode: Go; indent-tabs-mode: t -*-
463+
464+/*
465+ * Copyright (C) 2017 Canonical Ltd
466+ *
467+ * This program is free software: you can redistribute it and/or modify
468+ * it under the terms of the GNU General Public License version 3 as
469+ * published by the Free Software Foundation.
470+ *
471+ * This program is distributed in the hope that it will be useful,
472+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
473+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
474+ * GNU General Public License for more details.
475+ *
476+ * You should have received a copy of the GNU General Public License
477+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
478+ *
479+ */
480+
481+package main
482+
483+import (
484+ "os"
485+ "os/signal"
486+ "syscall"
487+
488+ "github.com/snapcore/snapd/tests/lib/fakestore/store"
489+)
490+
491+type cmdRun struct {
492+ TopDir string `long:"dir" description:"Directory to be used by the store to keep and serve snaps, <dir>/asserts is used for assertions"`
493+ Addr string `long:"addr" default:"localhost:11028" description:"Store address"`
494+ AssertFallback bool `long:"assert-fallback" description:"Fallback to the main online store for missing assertions"`
495+
496+ HttpProxy string `long:"http-proxy" description:"HTTP proxy address"`
497+ HttpsProxy string `long:"https-proxy" description:"HTTPS proxy address"`
498+}
499+
500+var shortRunHelp = "Run the store service"
501+
502+func (x *cmdRun) Execute(args []string) error {
503+ if x.HttpsProxy != "" {
504+ os.Setenv("https_proxy", x.HttpsProxy)
505+ }
506+ if x.HttpProxy != "" {
507+ os.Setenv("http_proxy", x.HttpProxy)
508+ }
509+
510+ return runServer(x.TopDir, x.Addr, x.AssertFallback)
511+}
512+
513+func init() {
514+ if _, err := parser.AddCommand("run", shortRunHelp, "", &cmdRun{}); err != nil {
515+ panic(err)
516+ }
517+}
518+
519+func runServer(topDir, addr string, assertFallback bool) error {
520+ st := store.NewStore(topDir, addr, assertFallback)
521+
522+ if err := st.Start(); err != nil {
523+ return err
524+ }
525+
526+ ch := make(chan os.Signal)
527+ signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
528+ <-ch
529+
530+ return st.Stop()
531+}
532diff --git a/tests/lib/fakestore/cmd/fakestore/main.go b/tests/lib/fakestore/cmd/fakestore/main.go
533new file mode 100644
534index 0000000..4e73ea8
535--- /dev/null
536+++ b/tests/lib/fakestore/cmd/fakestore/main.go
537@@ -0,0 +1,51 @@
538+// -*- Mode: Go; indent-tabs-mode: t -*-
539+
540+/*
541+ * Copyright (C) 2016 Canonical Ltd
542+ *
543+ * This program is free software: you can redistribute it and/or modify
544+ * it under the terms of the GNU General Public License version 3 as
545+ * published by the Free Software Foundation.
546+ *
547+ * This program is distributed in the hope that it will be useful,
548+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
549+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
550+ * GNU General Public License for more details.
551+ *
552+ * You should have received a copy of the GNU General Public License
553+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
554+ *
555+ */
556+
557+package main
558+
559+import (
560+ "fmt"
561+ "os"
562+
563+ "github.com/jessevdk/go-flags"
564+
565+ "github.com/snapcore/snapd/logger"
566+)
567+
568+type Options struct{}
569+
570+var parser = flags.NewParser(&Options{}, flags.Default)
571+
572+func main() {
573+ if err := logger.SimpleSetup(); err != nil {
574+ fmt.Fprintf(os.Stderr, "failed to activate logging: %v\n", err)
575+ os.Exit(1)
576+ }
577+ logger.Debugf("fakestore starting")
578+
579+ if err := run(); err != nil {
580+ fmt.Fprintf(os.Stderr, "error: %v\n", err)
581+ os.Exit(1)
582+ }
583+}
584+
585+func run() error {
586+ _, err := parser.Parse()
587+ return err
588+}
589diff --git a/tests/lib/fakestore/refresh/refresh.go b/tests/lib/fakestore/refresh/refresh.go
590new file mode 100644
591index 0000000..11dd429
592--- /dev/null
593+++ b/tests/lib/fakestore/refresh/refresh.go
594@@ -0,0 +1,258 @@
595+// -*- Mode: Go; indent-tabs-mode: t -*-
596+
597+/*
598+ * Copyright (C) 2016 Canonical Ltd
599+ *
600+ * This program is free software: you can redistribute it and/or modify
601+ * it under the terms of the GNU General Public License version 3 as
602+ * published by the Free Software Foundation.
603+ *
604+ * This program is distributed in the hope that it will be useful,
605+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
606+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
607+ * GNU General Public License for more details.
608+ *
609+ * You should have received a copy of the GNU General Public License
610+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
611+ *
612+ */
613+
614+package refresh
615+
616+import (
617+ "fmt"
618+ "io/ioutil"
619+ "os"
620+ "os/exec"
621+ "path/filepath"
622+ "strings"
623+ "time"
624+
625+ "github.com/snapcore/snapd/asserts"
626+ "github.com/snapcore/snapd/asserts/assertstest"
627+ "github.com/snapcore/snapd/asserts/snapasserts"
628+ "github.com/snapcore/snapd/asserts/sysdb"
629+ "github.com/snapcore/snapd/asserts/systestkeys"
630+ "github.com/snapcore/snapd/client"
631+ "github.com/snapcore/snapd/dirs"
632+ "github.com/snapcore/snapd/snap"
633+)
634+
635+func newAssertsDB() (*asserts.Database, error) {
636+ storePrivKey, _ := assertstest.ReadPrivKey(systestkeys.TestStorePrivKey)
637+ db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
638+ KeypairManager: asserts.NewMemoryKeypairManager(),
639+ Backstore: asserts.NewMemoryBackstore(),
640+ Trusted: sysdb.Trusted(),
641+ })
642+ if err != nil {
643+ return nil, err
644+ }
645+ // for signing
646+ db.ImportKey(storePrivKey)
647+
648+ return db, nil
649+}
650+
651+func MakeFakeRefreshForSnaps(snaps []string, blobDir string) error {
652+ db, err := newAssertsDB()
653+ if err != nil {
654+ return err
655+ }
656+
657+ var cliConfig client.Config
658+ cli := client.New(&cliConfig)
659+ retrieve := func(ref *asserts.Ref) (asserts.Assertion, error) {
660+ headers := make(map[string]string)
661+ for i, k := range ref.Type.PrimaryKey {
662+ headers[k] = ref.PrimaryKey[i]
663+ }
664+ as, err := cli.Known(ref.Type.Name, headers)
665+ if err != nil {
666+ return nil, err
667+ }
668+ switch len(as) {
669+ case 1:
670+ return as[0], nil
671+ case 0:
672+ return nil, &asserts.NotFoundError{Type: ref.Type, Headers: headers}
673+ default:
674+ panic(fmt.Sprintf("multiple assertions when retrieving by primary key: %v", ref))
675+ }
676+ }
677+
678+ save := func(a asserts.Assertion) error {
679+ err := db.Add(a)
680+ if err != nil {
681+ if _, ok := err.(*asserts.RevisionError); !ok {
682+ return err
683+ }
684+ }
685+ _, err = writeAssert(a, blobDir)
686+ return err
687+ }
688+
689+ f := asserts.NewFetcher(db, retrieve, save)
690+
691+ for _, snap := range snaps {
692+ if err := makeFakeRefreshForSnap(snap, blobDir, db, f); err != nil {
693+ return err
694+ }
695+ }
696+ return nil
697+}
698+
699+func writeAssert(a asserts.Assertion, targetDir string) (string, error) {
700+ ref := a.Ref()
701+ fn := fmt.Sprintf("%s.%s", strings.Join(ref.PrimaryKey, ","), ref.Type.Name)
702+ p := filepath.Join(targetDir, "asserts", fn)
703+ if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {
704+ return "", err
705+ }
706+ err := ioutil.WriteFile(p, asserts.Encode(a), 0644)
707+ return p, err
708+}
709+
710+func makeFakeRefreshForSnap(snap, targetDir string, db *asserts.Database, f asserts.Fetcher) error {
711+ // make a fake update snap in /var/tmp (which is not a tempfs)
712+ fakeUpdateDir, err := ioutil.TempDir("/var/tmp", "snap-build-")
713+ if err != nil {
714+ return fmt.Errorf("creating tmp for fake update: %v", err)
715+ }
716+ // ensure the "." of the squashfs has sane owner/permissions
717+ err = exec.Command("sudo", "chown", "root:root", fakeUpdateDir).Run()
718+ if err != nil {
719+ return fmt.Errorf("changing owner of fake update dir: %v", err)
720+ }
721+ err = exec.Command("sudo", "chmod", "0755", fakeUpdateDir).Run()
722+ if err != nil {
723+ return fmt.Errorf("changing permissions of fake update dir: %v", err)
724+ }
725+ defer exec.Command("sudo", "rm", "-rf", fakeUpdateDir)
726+
727+ origInfo, err := copySnap(snap, fakeUpdateDir)
728+ if err != nil {
729+ return fmt.Errorf("copying snap: %v", err)
730+ }
731+
732+ err = copySnapAsserts(origInfo, f)
733+ if err != nil {
734+ return fmt.Errorf("copying asserts: %v", err)
735+ }
736+
737+ // fake new version
738+ err = exec.Command("sudo", "sed", "-i", `s/version:\(.*\)/version:\1+fake1/`, filepath.Join(fakeUpdateDir, "meta/snap.yaml")).Run()
739+ if err != nil {
740+ return fmt.Errorf("changing fake snap version: %v", err)
741+ }
742+
743+ newInfo, err := buildSnap(fakeUpdateDir, targetDir)
744+ if err != nil {
745+ return err
746+ }
747+
748+ // new test-signed snap-revision
749+ err = makeNewSnapRevision(origInfo, newInfo, targetDir, db)
750+ if err != nil {
751+ return fmt.Errorf("cannot make new snap-revision: %v", err)
752+ }
753+
754+ return nil
755+}
756+
757+type info struct {
758+ revision string
759+ digest string
760+ size uint64
761+}
762+
763+func copySnap(snapName, targetDir string) (*info, error) {
764+ baseDir := filepath.Join(dirs.SnapMountDir, snapName)
765+ if _, err := os.Stat(baseDir); err != nil {
766+ return nil, err
767+ }
768+ sourceDir := filepath.Join(baseDir, "current")
769+ files, err := filepath.Glob(filepath.Join(sourceDir, "*"))
770+ if err != nil {
771+ return nil, err
772+ }
773+
774+ revnoDir, err := filepath.EvalSymlinks(sourceDir)
775+ if err != nil {
776+ return nil, err
777+ }
778+ origRevision := filepath.Base(revnoDir)
779+
780+ for _, m := range files {
781+ if err = exec.Command("sudo", "cp", "-a", m, targetDir).Run(); err != nil {
782+ return nil, err
783+
784+ }
785+ }
786+
787+ rev, err := snap.ParseRevision(origRevision)
788+ if err != nil {
789+ return nil, err
790+ }
791+
792+ place := snap.MinimalPlaceInfo(snapName, rev)
793+ origDigest, origSize, err := asserts.SnapFileSHA3_384(place.MountFile())
794+ if err != nil {
795+ return nil, err
796+ }
797+
798+ return &info{revision: origRevision, size: origSize, digest: origDigest}, nil
799+}
800+
801+func buildSnap(snapDir, targetDir string) (*info, error) {
802+ // build in /var/tmp (which is not a tempfs)
803+ cmd := exec.Command("snap", "pack", snapDir, targetDir)
804+ cmd.Env = append(os.Environ(), "TMPDIR=/var/tmp")
805+ output, err := cmd.CombinedOutput()
806+ if err != nil {
807+ return nil, fmt.Errorf("building fake snap: %v, output: %s", err, output)
808+ }
809+ out := strings.TrimSpace(string(output))
810+ if !strings.HasPrefix(out, "built: ") {
811+ return nil, fmt.Errorf("building fake snap got unexpected output: %s", output)
812+ }
813+ fn := out[len("built: "):]
814+
815+ newDigest, size, err := asserts.SnapFileSHA3_384(fn)
816+ if err != nil {
817+ return nil, err
818+ }
819+
820+ return &info{digest: newDigest, size: size}, nil
821+}
822+
823+func copySnapAsserts(info *info, f asserts.Fetcher) error {
824+ return snapasserts.FetchSnapAssertions(f, info.digest)
825+}
826+
827+func makeNewSnapRevision(orig, new *info, targetDir string, db *asserts.Database) error {
828+ a, err := db.Find(asserts.SnapRevisionType, map[string]string{
829+ "snap-sha3-384": orig.digest,
830+ })
831+ if err != nil {
832+ return err
833+ }
834+ origSnapRev := a.(*asserts.SnapRevision)
835+
836+ headers := map[string]interface{}{
837+ "authority-id": "testrootorg",
838+ "snap-sha3-384": new.digest,
839+ "snap-id": origSnapRev.SnapID(),
840+ "snap-size": fmt.Sprintf("%d", new.size),
841+ "snap-revision": fmt.Sprintf("%d", origSnapRev.SnapRevision()+1),
842+ "developer-id": origSnapRev.DeveloperID(),
843+ "timestamp": time.Now().Format(time.RFC3339),
844+ }
845+ a, err = db.Sign(asserts.SnapRevisionType, headers, nil, systestkeys.TestStoreKeyID)
846+ if err != nil {
847+ return err
848+ }
849+
850+ _, err = writeAssert(a, targetDir)
851+ return err
852+}
853diff --git a/tests/lib/fakestore/refresh/snap_asserts.go b/tests/lib/fakestore/refresh/snap_asserts.go
854new file mode 100644
855index 0000000..364c7f7
856--- /dev/null
857+++ b/tests/lib/fakestore/refresh/snap_asserts.go
858@@ -0,0 +1,95 @@
859+// -*- Mode: Go; indent-tabs-mode: t -*-
860+
861+/*
862+ * Copyright (C) 2017 Canonical Ltd
863+ *
864+ * This program is free software: you can redistribute it and/or modify
865+ * it under the terms of the GNU General Public License version 3 as
866+ * published by the Free Software Foundation.
867+ *
868+ * This program is distributed in the hope that it will be useful,
869+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
870+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
871+ * GNU General Public License for more details.
872+ *
873+ * You should have received a copy of the GNU General Public License
874+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
875+ *
876+ */
877+
878+package refresh
879+
880+import (
881+ "fmt"
882+ "path/filepath"
883+ "strings"
884+ "time"
885+
886+ "github.com/snapcore/snapd/asserts"
887+ "github.com/snapcore/snapd/asserts/systestkeys"
888+)
889+
890+func snapNameFromPath(snapPath string) string {
891+ return strings.Split(filepath.Base(snapPath), "_")[0]
892+}
893+
894+// TODO: also support reading/copying form a store snap
895+
896+func NewSnapRevision(targetDir string, snap string, headers map[string]interface{}) (string, error) {
897+ db, err := newAssertsDB()
898+ if err != nil {
899+ return "", err
900+ }
901+ digest, size, err := asserts.SnapFileSHA3_384(snap)
902+ if err != nil {
903+ return "", err
904+ }
905+
906+ fallbacks := map[string]interface{}{
907+ "developer-id": "testrootorg",
908+ "snap-id": snapNameFromPath(snap) + "-id",
909+ "snap-revision": "1",
910+ }
911+ for k, v := range fallbacks {
912+ if _, ok := headers[k]; !ok {
913+ headers[k] = v
914+ }
915+ }
916+ headers["authority-id"] = "testrootorg"
917+ headers["snap-sha3-384"] = digest
918+ headers["snap-size"] = fmt.Sprintf("%d", size)
919+ headers["timestamp"] = time.Now().Format(time.RFC3339)
920+
921+ a, err := db.Sign(asserts.SnapRevisionType, headers, nil, systestkeys.TestStoreKeyID)
922+ if err != nil {
923+ return "", err
924+ }
925+ return writeAssert(a, targetDir)
926+}
927+
928+func NewSnapDeclaration(targetDir string, snap string, headers map[string]interface{}) (string, error) {
929+ db, err := newAssertsDB()
930+ if err != nil {
931+ return "", err
932+ }
933+
934+ fallbacks := map[string]interface{}{
935+ "snap-id": snapNameFromPath(snap) + "-id",
936+ "snap-name": snapNameFromPath(snap),
937+ "publisher-id": "testrootorg",
938+ }
939+ for k, v := range fallbacks {
940+ if _, ok := headers[k]; !ok {
941+ headers[k] = v
942+ }
943+ }
944+ headers["authority-id"] = "testrootorg"
945+ headers["series"] = "16"
946+ headers["timestamp"] = time.Now().Format(time.RFC3339)
947+
948+ a, err := db.Sign(asserts.SnapDeclarationType, headers, nil, systestkeys.TestStoreKeyID)
949+ if err != nil {
950+ return "", err
951+ }
952+ return writeAssert(a, targetDir)
953+}
954diff --git a/tests/lib/fakestore/store/store.go b/tests/lib/fakestore/store/store.go
955new file mode 100644
956index 0000000..f2d16b5
957--- /dev/null
958+++ b/tests/lib/fakestore/store/store.go
959@@ -0,0 +1,720 @@
960+// -*- Mode: Go; indent-tabs-mode: t -*-
961+
962+/*
963+ * Copyright (C) 2016-2018 Canonical Ltd
964+ *
965+ * This program is free software: you can redistribute it and/or modify
966+ * it under the terms of the GNU General Public License version 3 as
967+ * published by the Free Software Foundation.
968+ *
969+ * This program is distributed in the hope that it will be useful,
970+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
971+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
972+ * GNU General Public License for more details.
973+ *
974+ * You should have received a copy of the GNU General Public License
975+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
976+ *
977+ */
978+
979+package store
980+
981+import (
982+ "encoding/base64"
983+ "encoding/json"
984+ "errors"
985+ "fmt"
986+ "io/ioutil"
987+ "net"
988+ "net/http"
989+ "path/filepath"
990+ "strings"
991+ "time"
992+
993+ "gopkg.in/tylerb/graceful.v1"
994+
995+ "github.com/snapcore/snapd/asserts"
996+ "github.com/snapcore/snapd/asserts/sysdb"
997+ "github.com/snapcore/snapd/asserts/systestkeys"
998+ "github.com/snapcore/snapd/httputil"
999+ "github.com/snapcore/snapd/osutil"
1000+ "github.com/snapcore/snapd/snap"
1001+ "github.com/snapcore/snapd/store"
1002+)
1003+
1004+func rootEndpoint(w http.ResponseWriter, req *http.Request) {
1005+ w.WriteHeader(418)
1006+ fmt.Fprintf(w, "I'm a teapot")
1007+}
1008+
1009+func hexify(in string) string {
1010+ bs, err := base64.RawURLEncoding.DecodeString(in)
1011+ if err != nil {
1012+ panic(err)
1013+ }
1014+ return fmt.Sprintf("%x", bs)
1015+}
1016+
1017+// Store is our snappy software store implementation
1018+type Store struct {
1019+ url string
1020+ blobDir string
1021+ assertDir string
1022+
1023+ assertFallback bool
1024+ fallback *store.Store
1025+
1026+ srv *graceful.Server
1027+}
1028+
1029+// NewStore creates a new store server serving snaps from the given top directory and assertions from topDir/asserts. If assertFallback is true missing assertions are looked up in the main online store.
1030+func NewStore(topDir, addr string, assertFallback bool) *Store {
1031+ mux := http.NewServeMux()
1032+ var sto *store.Store
1033+ if assertFallback {
1034+ httputil.SetUserAgentFromVersion("unknown", "fakestore")
1035+ sto = store.New(nil, nil)
1036+ }
1037+ store := &Store{
1038+ blobDir: topDir,
1039+ assertDir: filepath.Join(topDir, "asserts"),
1040+
1041+ assertFallback: assertFallback,
1042+ fallback: sto,
1043+
1044+ url: fmt.Sprintf("http://%s", addr),
1045+ srv: &graceful.Server{
1046+ Timeout: 2 * time.Second,
1047+
1048+ Server: &http.Server{
1049+ Addr: addr,
1050+ Handler: mux,
1051+ },
1052+ },
1053+ }
1054+
1055+ mux.HandleFunc("/", rootEndpoint)
1056+ mux.HandleFunc("/api/v1/snaps/search", store.searchEndpoint)
1057+ mux.HandleFunc("/api/v1/snaps/details/", store.detailsEndpoint)
1058+ mux.HandleFunc("/api/v1/snaps/metadata", store.bulkEndpoint)
1059+ mux.Handle("/download/", http.StripPrefix("/download/", http.FileServer(http.Dir(topDir))))
1060+ mux.HandleFunc("/api/v1/snaps/assertions/", store.assertionsEndpoint)
1061+ // v2
1062+ mux.HandleFunc("/v2/snaps/refresh", store.snapActionEndpoint)
1063+
1064+ return store
1065+}
1066+
1067+// URL returns the base-url that the store is listening on
1068+func (s *Store) URL() string {
1069+ return s.url
1070+}
1071+
1072+func (s *Store) SnapsDir() string {
1073+ return s.blobDir
1074+}
1075+
1076+// Start listening
1077+func (s *Store) Start() error {
1078+ l, err := net.Listen("tcp", s.srv.Addr)
1079+ if err != nil {
1080+ return err
1081+ }
1082+
1083+ go s.srv.Serve(l)
1084+ return nil
1085+}
1086+
1087+// Stop stops the server
1088+func (s *Store) Stop() error {
1089+ timeoutTime := 2000 * time.Millisecond
1090+ s.srv.Stop(timeoutTime / 2)
1091+
1092+ select {
1093+ case <-s.srv.StopChan():
1094+ case <-time.After(timeoutTime):
1095+ return fmt.Errorf("store failed to stop after %s", timeoutTime)
1096+ }
1097+
1098+ return nil
1099+}
1100+
1101+var (
1102+ defaultDeveloper = "canonical"
1103+ defaultDeveloperID = "canonical"
1104+ defaultRevision = 424242
1105+)
1106+
1107+func makeRevision(info *snap.Info) int {
1108+ // TODO: This is a hack to ensure we have higher
1109+ // revisions here than locally. The fake
1110+ // snaps get versions like
1111+ // "1.0+fake1+fake1+fake1"
1112+ // so we can use this for now to generate
1113+ // fake revisions. However in the longer
1114+ // term we should read the real revision
1115+ // of the snap, increment and add a ".aux"
1116+ // file to the download directory of the
1117+ // store that contains the revision and the
1118+ // developer. The fake-store can then read
1119+ // that file when sending the reply.
1120+ n := strings.Count(info.Version, "+fake") + 1
1121+ return n * defaultRevision
1122+}
1123+
1124+type essentialInfo struct {
1125+ Name string
1126+ SnapID string
1127+ DeveloperID string
1128+ DevelName string
1129+ Revision int
1130+ Version string
1131+ Size uint64
1132+ Digest string
1133+}
1134+
1135+var errInfo = errors.New("cannot get info")
1136+
1137+func snapEssentialInfo(w http.ResponseWriter, fn, snapID string, bs asserts.Backstore) (*essentialInfo, error) {
1138+ snapFile, err := snap.Open(fn)
1139+ if err != nil {
1140+ http.Error(w, fmt.Sprintf("cannot read: %v: %v", fn, err), 400)
1141+ return nil, errInfo
1142+ }
1143+
1144+ restoreSanitize := snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})
1145+ defer restoreSanitize()
1146+
1147+ info, err := snap.ReadInfoFromSnapFile(snapFile, nil)
1148+ if err != nil {
1149+ http.Error(w, fmt.Sprintf("cannot get info for: %v: %v", fn, err), 400)
1150+ return nil, errInfo
1151+ }
1152+
1153+ snapDigest, size, err := asserts.SnapFileSHA3_384(fn)
1154+ if err != nil {
1155+ http.Error(w, fmt.Sprintf("cannot get digest for: %v: %v", fn, err), 400)
1156+ return nil, errInfo
1157+ }
1158+
1159+ snapRev, devAcct, err := findSnapRevision(snapDigest, bs)
1160+ if err != nil && !asserts.IsNotFound(err) {
1161+ http.Error(w, fmt.Sprintf("cannot get info for: %v: %v", fn, err), 400)
1162+ return nil, errInfo
1163+ }
1164+
1165+ var devel, develID string
1166+ var revision int
1167+ if snapRev != nil {
1168+ snapID = snapRev.SnapID()
1169+ develID = snapRev.DeveloperID()
1170+ devel = devAcct.Username()
1171+ revision = snapRev.SnapRevision()
1172+ } else {
1173+ // XXX: fallback until we are always assertion based
1174+ develID = defaultDeveloperID
1175+ devel = defaultDeveloper
1176+ revision = makeRevision(info)
1177+ }
1178+
1179+ return &essentialInfo{
1180+ Name: info.SnapName(),
1181+ SnapID: snapID,
1182+ DeveloperID: develID,
1183+ DevelName: devel,
1184+ Revision: revision,
1185+ Version: info.Version,
1186+ Digest: snapDigest,
1187+ Size: size,
1188+ }, nil
1189+}
1190+
1191+type searchPayloadJSON struct {
1192+ Packages []detailsReplyJSON `json:"clickindex:package"`
1193+}
1194+
1195+type searchReplyJSON struct {
1196+ Payload searchPayloadJSON `json:"_embedded"`
1197+}
1198+
1199+type detailsReplyJSON struct {
1200+ Architectures []string `json:"architecture"`
1201+ SnapID string `json:"snap_id"`
1202+ PackageName string `json:"package_name"`
1203+ Developer string `json:"origin"`
1204+ DeveloperID string `json:"developer_id"`
1205+ AnonDownloadURL string `json:"anon_download_url"`
1206+ DownloadURL string `json:"download_url"`
1207+ Version string `json:"version"`
1208+ Revision int `json:"revision"`
1209+ DownloadDigest string `json:"download_sha3_384"`
1210+}
1211+
1212+func (s *Store) searchEndpoint(w http.ResponseWriter, req *http.Request) {
1213+ w.WriteHeader(501)
1214+ fmt.Fprintf(w, "search not implemented")
1215+}
1216+
1217+func (s *Store) detailsEndpoint(w http.ResponseWriter, req *http.Request) {
1218+ pkg := strings.TrimPrefix(req.URL.Path, "/api/v1/snaps/details/")
1219+ if pkg == req.URL.Path {
1220+ panic("how?")
1221+ }
1222+
1223+ bs, err := s.collectAssertions()
1224+ if err != nil {
1225+ http.Error(w, fmt.Sprintf("internal error collecting assertions: %v", err), 500)
1226+ return
1227+ }
1228+ snaps, err := s.collectSnaps()
1229+ if err != nil {
1230+ http.Error(w, fmt.Sprintf("internal error collecting snaps: %v", err), 500)
1231+ return
1232+ }
1233+
1234+ fn, ok := snaps[pkg]
1235+ if !ok {
1236+ http.NotFound(w, req)
1237+ return
1238+ }
1239+
1240+ essInfo, err := snapEssentialInfo(w, fn, "", bs)
1241+ if essInfo == nil {
1242+ if err != errInfo {
1243+ panic(err)
1244+ }
1245+ return
1246+ }
1247+
1248+ details := detailsReplyJSON{
1249+ Architectures: []string{"all"},
1250+ SnapID: essInfo.SnapID,
1251+ PackageName: essInfo.Name,
1252+ Developer: essInfo.DevelName,
1253+ DeveloperID: essInfo.DeveloperID,
1254+ AnonDownloadURL: fmt.Sprintf("%s/download/%s", s.URL(), filepath.Base(fn)),
1255+ DownloadURL: fmt.Sprintf("%s/download/%s", s.URL(), filepath.Base(fn)),
1256+ Version: essInfo.Version,
1257+ Revision: essInfo.Revision,
1258+ DownloadDigest: hexify(essInfo.Digest),
1259+ }
1260+
1261+ // use indent because this is a development tool, output
1262+ // should look nice
1263+ out, err := json.MarshalIndent(details, "", " ")
1264+ if err != nil {
1265+ http.Error(w, fmt.Sprintf("cannot marshal: %v: %v", details, err), 400)
1266+ return
1267+ }
1268+ w.Write(out)
1269+}
1270+
1271+func (s *Store) collectSnaps() (map[string]string, error) {
1272+ snapFns, err := filepath.Glob(filepath.Join(s.blobDir, "*.snap"))
1273+ if err != nil {
1274+ return nil, err
1275+ }
1276+
1277+ snaps := map[string]string{}
1278+
1279+ restoreSanitize := snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})
1280+ defer restoreSanitize()
1281+
1282+ for _, fn := range snapFns {
1283+ snapFile, err := snap.Open(fn)
1284+ if err != nil {
1285+ return nil, err
1286+ }
1287+ info, err := snap.ReadInfoFromSnapFile(snapFile, nil)
1288+ if err != nil {
1289+ return nil, err
1290+ }
1291+ snaps[info.SnapName()] = fn
1292+ }
1293+
1294+ return snaps, err
1295+}
1296+
1297+type candidateSnap struct {
1298+ SnapID string `json:"snap_id"`
1299+}
1300+
1301+type bulkReqJSON struct {
1302+ CandidateSnaps []candidateSnap `json:"snaps"`
1303+ Fields []string `json:"fields"`
1304+}
1305+
1306+type payload struct {
1307+ Packages []detailsReplyJSON `json:"clickindex:package"`
1308+}
1309+
1310+type bulkReplyJSON struct {
1311+ Payload payload `json:"_embedded"`
1312+}
1313+
1314+var someSnapIDtoName = map[string]map[string]string{
1315+ "production": {
1316+ "b8X2psL1ryVrPt5WEmpYiqfr5emixTd7": "ubuntu-core",
1317+ "99T7MUlRhtI3U0QFgl5mXXESAiSwt776": "core",
1318+ "bul8uZn9U3Ll4ke6BMqvNVEZjuJCSQvO": "canonical-pc",
1319+ "SkKeDk2PRgBrX89DdgULk3pyY5DJo6Jk": "canonical-pc-linux",
1320+ "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw": "test-snapd-tools",
1321+ "Wcs8QL2iRQMjsPYQ4qz4V1uOlElZ1ZOb": "test-snapd-python-webserver",
1322+ "DVvhXhpa9oJjcm0rnxfxftH1oo5vTW1M": "test-snapd-go-webserver",
1323+ },
1324+ "staging": {
1325+ "xMNMpEm0COPZy7jq9YRwWVLCD9q5peow": "core",
1326+ "02AHdOomTzby7gTaiLX3M3SGMmXDfLJp": "test-snapd-tools",
1327+ "uHjTANBWSXSiYzNOUXZNDnOSH3POSqWS": "test-snapd-python-webserver",
1328+ "edmdK5G9fP1q1bGyrjnaDXS4RkdjiTGV": "test-snapd-go-webserver",
1329+ },
1330+}
1331+
1332+func (s *Store) bulkEndpoint(w http.ResponseWriter, req *http.Request) {
1333+ var pkgs bulkReqJSON
1334+ var replyData bulkReplyJSON
1335+
1336+ decoder := json.NewDecoder(req.Body)
1337+ if err := decoder.Decode(&pkgs); err != nil {
1338+ http.Error(w, fmt.Sprintf("cannot decode request body: %v", err), 400)
1339+ return
1340+ }
1341+
1342+ bs, err := s.collectAssertions()
1343+ if err != nil {
1344+ http.Error(w, fmt.Sprintf("internal error collecting assertions: %v", err), 500)
1345+ return
1346+ }
1347+
1348+ var remoteStore string
1349+ if osutil.GetenvBool("SNAPPY_USE_STAGING_STORE") {
1350+ remoteStore = "staging"
1351+ } else {
1352+ remoteStore = "production"
1353+ }
1354+ snapIDtoName, err := addSnapIDs(bs, someSnapIDtoName[remoteStore])
1355+ if err != nil {
1356+ http.Error(w, fmt.Sprintf("internal error collecting snapIDs: %v", err), 500)
1357+ return
1358+ }
1359+
1360+ snaps, err := s.collectSnaps()
1361+ if err != nil {
1362+ http.Error(w, fmt.Sprintf("internal error collecting snaps: %v", err), 500)
1363+ return
1364+ }
1365+
1366+ // check if we have downloadable snap of the given SnapID
1367+ for _, pkg := range pkgs.CandidateSnaps {
1368+
1369+ name := snapIDtoName[pkg.SnapID]
1370+ if name == "" {
1371+ http.Error(w, fmt.Sprintf("unknown snap-id: %q", pkg.SnapID), 400)
1372+ return
1373+ }
1374+
1375+ if fn, ok := snaps[name]; ok {
1376+ essInfo, err := snapEssentialInfo(w, fn, pkg.SnapID, bs)
1377+ if essInfo == nil {
1378+ if err != errInfo {
1379+ panic(err)
1380+ }
1381+ return
1382+ }
1383+
1384+ replyData.Payload.Packages = append(replyData.Payload.Packages, detailsReplyJSON{
1385+ Architectures: []string{"all"},
1386+ SnapID: essInfo.SnapID,
1387+ PackageName: essInfo.Name,
1388+ Developer: essInfo.DevelName,
1389+ DeveloperID: essInfo.DeveloperID,
1390+ DownloadURL: fmt.Sprintf("%s/download/%s", s.URL(), filepath.Base(fn)),
1391+ AnonDownloadURL: fmt.Sprintf("%s/download/%s", s.URL(), filepath.Base(fn)),
1392+ Version: essInfo.Version,
1393+ Revision: essInfo.Revision,
1394+ DownloadDigest: hexify(essInfo.Digest),
1395+ })
1396+ }
1397+ }
1398+
1399+ // use indent because this is a development tool, output
1400+ // should look nice
1401+ out, err := json.MarshalIndent(replyData, "", " ")
1402+ if err != nil {
1403+ http.Error(w, fmt.Sprintf("cannot marshal: %v: %v", replyData, err), 400)
1404+ return
1405+ }
1406+ w.Write(out)
1407+
1408+}
1409+
1410+func (s *Store) collectAssertions() (asserts.Backstore, error) {
1411+ bs := asserts.NewMemoryBackstore()
1412+
1413+ add := func(a asserts.Assertion) {
1414+ bs.Put(a.Type(), a)
1415+ }
1416+
1417+ for _, t := range sysdb.Trusted() {
1418+ add(t)
1419+ }
1420+ add(systestkeys.TestRootAccount)
1421+ add(systestkeys.TestRootAccountKey)
1422+ add(systestkeys.TestStoreAccountKey)
1423+
1424+ aFiles, err := filepath.Glob(filepath.Join(s.assertDir, "*"))
1425+ if err != nil {
1426+ return nil, err
1427+ }
1428+
1429+ for _, fn := range aFiles {
1430+ b, err := ioutil.ReadFile(fn)
1431+ if err != nil {
1432+ return nil, err
1433+ }
1434+
1435+ a, err := asserts.Decode(b)
1436+ if err != nil {
1437+ return nil, err
1438+ }
1439+
1440+ add(a)
1441+ }
1442+
1443+ return bs, nil
1444+}
1445+
1446+type currentSnap struct {
1447+ SnapID string `json:"snap-id"`
1448+ InstanceKey string `json:"instance-key"`
1449+}
1450+
1451+type snapAction struct {
1452+ Action string `json:"action"`
1453+ InstanceKey string `json:"instance-key"`
1454+ SnapID string `json:"snap-id"`
1455+ Name string `json:"name"`
1456+}
1457+
1458+type snapActionRequest struct {
1459+ Context []currentSnap `json:"context"`
1460+ Fields []string `json:"fields"`
1461+ Actions []snapAction `json:"actions"`
1462+}
1463+
1464+type snapActionResult struct {
1465+ Result string `json:"result"`
1466+ InstanceKey string `json:"instance-key"`
1467+ SnapID string `json:"snap-id"`
1468+ Name string `json:"name"`
1469+ Snap detailsResultV2 `json:"snap"`
1470+}
1471+
1472+type snapActionResultList struct {
1473+ Results []*snapActionResult `json:"results"`
1474+}
1475+
1476+type detailsResultV2 struct {
1477+ Architectures []string `json:"architectures"`
1478+ SnapID string `json:"snap-id"`
1479+ Name string `json:"name"`
1480+ Publisher struct {
1481+ ID string `json:"id"`
1482+ Username string `json:"username"`
1483+ } `json:"publisher"`
1484+ Download struct {
1485+ URL string `json:"url"`
1486+ Sha3_384 string `json:"sha3-384"`
1487+ Size uint64 `json:"size"`
1488+ } `json:"download"`
1489+ Version string `json:"version"`
1490+ Revision int `json:"revision"`
1491+}
1492+
1493+func (s *Store) snapActionEndpoint(w http.ResponseWriter, req *http.Request) {
1494+ var reqData snapActionRequest
1495+ var replyData snapActionResultList
1496+
1497+ decoder := json.NewDecoder(req.Body)
1498+ if err := decoder.Decode(&reqData); err != nil {
1499+ http.Error(w, fmt.Sprintf("cannot decode request body: %v", err), 400)
1500+ return
1501+ }
1502+
1503+ bs, err := s.collectAssertions()
1504+ if err != nil {
1505+ http.Error(w, fmt.Sprintf("internal error collecting assertions: %v", err), 500)
1506+ return
1507+ }
1508+
1509+ var remoteStore string
1510+ if osutil.GetenvBool("SNAPPY_USE_STAGING_STORE") {
1511+ remoteStore = "staging"
1512+ } else {
1513+ remoteStore = "production"
1514+ }
1515+ snapIDtoName, err := addSnapIDs(bs, someSnapIDtoName[remoteStore])
1516+ if err != nil {
1517+ http.Error(w, fmt.Sprintf("internal error collecting snapIDs: %v", err), 500)
1518+ return
1519+ }
1520+
1521+ snaps, err := s.collectSnaps()
1522+ if err != nil {
1523+ http.Error(w, fmt.Sprintf("internal error collecting snaps: %v", err), 500)
1524+ return
1525+ }
1526+
1527+ actions := reqData.Actions
1528+ if len(actions) == 1 && actions[0].Action == "refresh-all" {
1529+ actions = make([]snapAction, len(reqData.Context))
1530+ for i, s := range reqData.Context {
1531+ actions[i] = snapAction{
1532+ Action: "refresh",
1533+ SnapID: s.SnapID,
1534+ InstanceKey: s.InstanceKey,
1535+ }
1536+ }
1537+ }
1538+
1539+ // check if we have downloadable snap of the given SnapID or name
1540+ for _, a := range actions {
1541+ name := a.Name
1542+ snapID := a.SnapID
1543+ if a.Action == "refresh" {
1544+ name = snapIDtoName[snapID]
1545+ }
1546+
1547+ if name == "" {
1548+ http.Error(w, fmt.Sprintf("unknown snap-id: %q", snapID), 400)
1549+ return
1550+ }
1551+
1552+ if fn, ok := snaps[name]; ok {
1553+ essInfo, err := snapEssentialInfo(w, fn, snapID, bs)
1554+ if essInfo == nil {
1555+ if err != errInfo {
1556+ panic(err)
1557+ }
1558+ return
1559+ }
1560+
1561+ res := &snapActionResult{
1562+ Result: a.Action,
1563+ InstanceKey: a.InstanceKey,
1564+ SnapID: essInfo.SnapID,
1565+ Name: essInfo.Name,
1566+ Snap: detailsResultV2{
1567+ Architectures: []string{"all"},
1568+ SnapID: essInfo.SnapID,
1569+ Name: essInfo.Name,
1570+ Version: essInfo.Version,
1571+ Revision: essInfo.Revision,
1572+ },
1573+ }
1574+ res.Snap.Publisher.ID = essInfo.DeveloperID
1575+ res.Snap.Publisher.Username = essInfo.DevelName
1576+ res.Snap.Download.URL = fmt.Sprintf("%s/download/%s", s.URL(), filepath.Base(fn))
1577+ res.Snap.Download.Sha3_384 = hexify(essInfo.Digest)
1578+ res.Snap.Download.Size = essInfo.Size
1579+ replyData.Results = append(replyData.Results, res)
1580+ }
1581+ }
1582+
1583+ // use indent because this is a development tool, output
1584+ // should look nice
1585+ out, err := json.MarshalIndent(replyData, "", " ")
1586+ if err != nil {
1587+ http.Error(w, fmt.Sprintf("cannot marshal: %v: %v", replyData, err), 400)
1588+ return
1589+ }
1590+ w.Write(out)
1591+}
1592+
1593+func (s *Store) retrieveAssertion(bs asserts.Backstore, assertType *asserts.AssertionType, primaryKey []string) (asserts.Assertion, error) {
1594+ a, err := bs.Get(assertType, primaryKey, assertType.MaxSupportedFormat())
1595+ if asserts.IsNotFound(err) && s.assertFallback {
1596+ return s.fallback.Assertion(assertType, primaryKey, nil)
1597+ }
1598+ return a, err
1599+}
1600+
1601+func (s *Store) assertionsEndpoint(w http.ResponseWriter, req *http.Request) {
1602+ assertPath := strings.TrimPrefix(req.URL.Path, "/api/v1/snaps/assertions/")
1603+
1604+ bs, err := s.collectAssertions()
1605+ if err != nil {
1606+ http.Error(w, fmt.Sprintf("internal error collecting assertions: %v", err), 500)
1607+ return
1608+ }
1609+
1610+ comps := strings.Split(assertPath, "/")
1611+
1612+ if len(comps) == 0 {
1613+ http.Error(w, "missing assertion type", 400)
1614+ return
1615+
1616+ }
1617+
1618+ typ := asserts.Type(comps[0])
1619+ if typ == nil {
1620+ http.Error(w, fmt.Sprintf("unknown assertion type: %s", comps[0]), 400)
1621+ return
1622+ }
1623+
1624+ if len(typ.PrimaryKey) != len(comps)-1 {
1625+ http.Error(w, fmt.Sprintf("wrong primary key length: %v", comps), 400)
1626+ return
1627+ }
1628+
1629+ a, err := s.retrieveAssertion(bs, typ, comps[1:])
1630+ if asserts.IsNotFound(err) {
1631+ w.Header().Set("Content-Type", "application/problem+json")
1632+ w.WriteHeader(404)
1633+ w.Write([]byte(`{"status": 404}`))
1634+ return
1635+ }
1636+ if err != nil {
1637+ http.Error(w, fmt.Sprintf("cannot retrieve assertion %v: %v", comps, err), 400)
1638+ return
1639+ }
1640+
1641+ w.Header().Set("Content-Type", asserts.MediaType)
1642+ w.WriteHeader(200)
1643+ w.Write(asserts.Encode(a))
1644+}
1645+
1646+func addSnapIDs(bs asserts.Backstore, initial map[string]string) (map[string]string, error) {
1647+ m := make(map[string]string)
1648+ for id, name := range initial {
1649+ m[id] = name
1650+ }
1651+
1652+ hit := func(a asserts.Assertion) {
1653+ decl := a.(*asserts.SnapDeclaration)
1654+ m[decl.SnapID()] = decl.SnapName()
1655+ }
1656+
1657+ err := bs.Search(asserts.SnapDeclarationType, nil, hit, asserts.SnapDeclarationType.MaxSupportedFormat())
1658+ if err != nil {
1659+ return nil, err
1660+ }
1661+
1662+ return m, nil
1663+}
1664+
1665+func findSnapRevision(snapDigest string, bs asserts.Backstore) (*asserts.SnapRevision, *asserts.Account, error) {
1666+ a, err := bs.Get(asserts.SnapRevisionType, []string{snapDigest}, asserts.SnapRevisionType.MaxSupportedFormat())
1667+ if err != nil {
1668+ return nil, nil, err
1669+ }
1670+ snapRev := a.(*asserts.SnapRevision)
1671+
1672+ a, err = bs.Get(asserts.AccountType, []string{snapRev.DeveloperID()}, asserts.AccountType.MaxSupportedFormat())
1673+ if err != nil {
1674+ return nil, nil, err
1675+ }
1676+ devAcct := a.(*asserts.Account)
1677+
1678+ return snapRev, devAcct, nil
1679+}
1680diff --git a/tests/lib/fakestore/store/store_test.go b/tests/lib/fakestore/store/store_test.go
1681new file mode 100644
1682index 0000000..e4334f1
1683--- /dev/null
1684+++ b/tests/lib/fakestore/store/store_test.go
1685@@ -0,0 +1,562 @@
1686+// -*- Mode: Go; indent-tabs-mode: t -*-
1687+
1688+/*
1689+ * Copyright (C) 2014-2018 Canonical Ltd
1690+ *
1691+ * This program is free software: you can redistribute it and/or modify
1692+ * it under the terms of the GNU General Public License version 3 as
1693+ * published by the Free Software Foundation.
1694+ *
1695+ * This program is distributed in the hope that it will be useful,
1696+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1697+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1698+ * GNU General Public License for more details.
1699+ *
1700+ * You should have received a copy of the GNU General Public License
1701+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1702+ *
1703+ */
1704+
1705+package store
1706+
1707+import (
1708+ "bytes"
1709+ "encoding/json"
1710+ "io/ioutil"
1711+ "net/http"
1712+ "os"
1713+ "path/filepath"
1714+ "testing"
1715+ "text/template"
1716+
1717+ "github.com/snapcore/snapd/asserts"
1718+ "github.com/snapcore/snapd/asserts/systestkeys"
1719+ "github.com/snapcore/snapd/osutil"
1720+ "github.com/snapcore/snapd/snap/snaptest"
1721+
1722+ . "gopkg.in/check.v1"
1723+)
1724+
1725+// Hook up check.v1 into the "go test" runner
1726+func Test(t *testing.T) { TestingT(t) }
1727+
1728+type storeTestSuite struct {
1729+ client *http.Client
1730+ store *Store
1731+}
1732+
1733+var _ = Suite(&storeTestSuite{})
1734+
1735+var defaultAddr = "localhost:23321"
1736+
1737+func getSha(fn string) (string, uint64) {
1738+ snapDigest, size, err := asserts.SnapFileSHA3_384(fn)
1739+ if err != nil {
1740+ panic(err)
1741+ }
1742+ return hexify(snapDigest), size
1743+}
1744+
1745+func (s *storeTestSuite) SetUpTest(c *C) {
1746+ topdir := c.MkDir()
1747+ err := os.Mkdir(filepath.Join(topdir, "asserts"), 0755)
1748+ c.Assert(err, IsNil)
1749+ s.store = NewStore(topdir, defaultAddr, false)
1750+ err = s.store.Start()
1751+ c.Assert(err, IsNil)
1752+
1753+ transport := &http.Transport{}
1754+ s.client = &http.Client{
1755+ Transport: transport,
1756+ }
1757+}
1758+
1759+func (s *storeTestSuite) TearDownTest(c *C) {
1760+ s.client.Transport.(*http.Transport).CloseIdleConnections()
1761+ err := s.store.Stop()
1762+ c.Assert(err, IsNil)
1763+}
1764+
1765+// StoreGet gets the given from the store
1766+func (s *storeTestSuite) StoreGet(path string) (*http.Response, error) {
1767+ return s.client.Get(s.store.URL() + path)
1768+}
1769+
1770+func (s *storeTestSuite) StorePostJSON(path string, content []byte) (*http.Response, error) {
1771+ r := bytes.NewReader(content)
1772+ return s.client.Post(s.store.URL()+path, "application/json", r)
1773+}
1774+
1775+func (s *storeTestSuite) TestStoreURL(c *C) {
1776+ c.Assert(s.store.URL(), Equals, "http://"+defaultAddr)
1777+}
1778+
1779+func (s *storeTestSuite) TestTrivialGetWorks(c *C) {
1780+ resp, err := s.StoreGet("/")
1781+ c.Assert(err, IsNil)
1782+ defer resp.Body.Close()
1783+
1784+ c.Assert(resp.StatusCode, Equals, 418)
1785+ body, err := ioutil.ReadAll(resp.Body)
1786+ c.Assert(err, IsNil)
1787+ c.Assert(string(body), Equals, "I'm a teapot")
1788+
1789+}
1790+
1791+func (s *storeTestSuite) TestSearchEndpoint(c *C) {
1792+ resp, err := s.StoreGet("/api/v1/snaps/search")
1793+ c.Assert(err, IsNil)
1794+ defer resp.Body.Close()
1795+
1796+ c.Assert(resp.StatusCode, Equals, 501)
1797+ body, err := ioutil.ReadAll(resp.Body)
1798+ c.Assert(err, IsNil)
1799+ c.Assert(string(body), Equals, "search not implemented")
1800+
1801+}
1802+
1803+func (s *storeTestSuite) TestDetailsEndpointWithAssertions(c *C) {
1804+ snapFn := s.makeTestSnap(c, "name: foo\nversion: 7")
1805+ s.makeAssertions(c, snapFn, "foo", "xidididididididididididididididid", "foo-devel", "foo-devel-id", 77)
1806+
1807+ resp, err := s.StoreGet(`/api/v1/snaps/details/foo`)
1808+ c.Assert(err, IsNil)
1809+ defer resp.Body.Close()
1810+
1811+ c.Assert(resp.StatusCode, Equals, 200)
1812+
1813+ var body map[string]interface{}
1814+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
1815+ sha3_384, _ := getSha(snapFn)
1816+ c.Check(body, DeepEquals, map[string]interface{}{
1817+ "architecture": []interface{}{"all"},
1818+ "snap_id": "xidididididididididididididididid",
1819+ "package_name": "foo",
1820+ "origin": "foo-devel",
1821+ "developer_id": "foo-devel-id",
1822+ "anon_download_url": s.store.URL() + "/download/foo_7_all.snap",
1823+ "download_url": s.store.URL() + "/download/foo_7_all.snap",
1824+ "version": "7",
1825+ "revision": float64(77),
1826+ "download_sha3_384": sha3_384,
1827+ })
1828+}
1829+
1830+func (s *storeTestSuite) TestDetailsEndpoint(c *C) {
1831+ snapFn := s.makeTestSnap(c, "name: foo\nversion: 1")
1832+ resp, err := s.StoreGet(`/api/v1/snaps/details/foo`)
1833+ c.Assert(err, IsNil)
1834+ defer resp.Body.Close()
1835+
1836+ c.Assert(resp.StatusCode, Equals, 200)
1837+
1838+ var body map[string]interface{}
1839+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
1840+ sha3_384, _ := getSha(snapFn)
1841+ c.Check(body, DeepEquals, map[string]interface{}{
1842+ "architecture": []interface{}{"all"},
1843+ "snap_id": "",
1844+ "package_name": "foo",
1845+ "origin": "canonical",
1846+ "developer_id": "canonical",
1847+ "anon_download_url": s.store.URL() + "/download/foo_1_all.snap",
1848+ "download_url": s.store.URL() + "/download/foo_1_all.snap",
1849+ "version": "1",
1850+ "revision": float64(424242),
1851+ "download_sha3_384": sha3_384,
1852+ })
1853+}
1854+
1855+func (s *storeTestSuite) TestBulkEndpoint(c *C) {
1856+ snapFn := s.makeTestSnap(c, "name: test-snapd-tools\nversion: 1")
1857+
1858+ // note that we send the test-snapd-tools snapID here
1859+ resp, err := s.StorePostJSON("/api/v1/snaps/metadata", []byte(`{
1860+"snaps": [{"snap_id":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","channel":"stable","revision":1}]
1861+}`))
1862+ c.Assert(err, IsNil)
1863+ defer resp.Body.Close()
1864+
1865+ c.Assert(resp.StatusCode, Equals, 200)
1866+
1867+ var body struct {
1868+ Top struct {
1869+ Cat []map[string]interface{} `json:"clickindex:package"`
1870+ } `json:"_embedded"`
1871+ }
1872+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
1873+ sha3_384, _ := getSha(snapFn)
1874+ c.Check(body.Top.Cat, DeepEquals, []map[string]interface{}{{
1875+ "architecture": []interface{}{"all"},
1876+ "snap_id": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
1877+ "package_name": "test-snapd-tools",
1878+ "origin": "canonical",
1879+ "developer_id": "canonical",
1880+ "anon_download_url": s.store.URL() + "/download/test-snapd-tools_1_all.snap",
1881+ "download_url": s.store.URL() + "/download/test-snapd-tools_1_all.snap",
1882+ "version": "1",
1883+ "revision": float64(424242),
1884+ "download_sha3_384": sha3_384,
1885+ }})
1886+}
1887+
1888+func (s *storeTestSuite) TestBulkEndpointWithAssertions(c *C) {
1889+ snapFn := s.makeTestSnap(c, "name: foo\nversion: 10")
1890+ s.makeAssertions(c, snapFn, "foo", "xidididididididididididididididid", "foo-devel", "foo-devel-id", 99)
1891+
1892+ resp, err := s.StorePostJSON("/api/v1/snaps/metadata", []byte(`{
1893+"snaps": [{"snap_id":"xidididididididididididididididid","channel":"stable","revision":1}]
1894+}`))
1895+ c.Assert(err, IsNil)
1896+ defer resp.Body.Close()
1897+
1898+ c.Assert(resp.StatusCode, Equals, 200)
1899+ var body struct {
1900+ Top struct {
1901+ Cat []map[string]interface{} `json:"clickindex:package"`
1902+ } `json:"_embedded"`
1903+ }
1904+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
1905+ sha3_384, _ := getSha(snapFn)
1906+ c.Check(body.Top.Cat, DeepEquals, []map[string]interface{}{{
1907+ "architecture": []interface{}{"all"},
1908+ "snap_id": "xidididididididididididididididid",
1909+ "package_name": "foo",
1910+ "origin": "foo-devel",
1911+ "developer_id": "foo-devel-id",
1912+ "anon_download_url": s.store.URL() + "/download/foo_10_all.snap",
1913+ "download_url": s.store.URL() + "/download/foo_10_all.snap",
1914+ "version": "10",
1915+ "revision": float64(99),
1916+ "download_sha3_384": sha3_384,
1917+ }})
1918+}
1919+
1920+func (s *storeTestSuite) makeTestSnap(c *C, snapYamlContent string) string {
1921+ fn := snaptest.MakeTestSnapWithFiles(c, snapYamlContent, nil)
1922+ dst := filepath.Join(s.store.blobDir, filepath.Base(fn))
1923+ err := osutil.CopyFile(fn, dst, 0)
1924+ c.Assert(err, IsNil)
1925+ return dst
1926+}
1927+
1928+var (
1929+ tSnapDecl = template.Must(template.New("snap-decl").Parse(`type: snap-declaration
1930+authority-id: testrootorg
1931+series: 16
1932+snap-id: {{.SnapID}}
1933+publisher-id: {{.DeveloperID}}
1934+snap-name: {{.Name}}
1935+timestamp: 2016-08-19T19:19:19Z
1936+sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
1937+
1938+AXNpZw=
1939+`))
1940+ tSnapRev = template.Must(template.New("snap-rev").Parse(`type: snap-revision
1941+authority-id: testrootorg
1942+snap-sha3-384: {{.Digest}}
1943+developer-id: {{.DeveloperID}}
1944+snap-id: {{.SnapID}}
1945+snap-revision: {{.Revision}}
1946+snap-size: {{.Size}}
1947+timestamp: 2016-08-19T19:19:19Z
1948+sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
1949+
1950+AXNpZw=
1951+`))
1952+ tAccount = template.Must(template.New("acct").Parse(`type: account
1953+authority-id: testrootorg
1954+account-id: {{.DeveloperID}}
1955+display-name: {{.DevelName}} Dev
1956+username: {{.DevelName}}
1957+validation: unproven
1958+timestamp: 2016-08-19T19:19:19Z
1959+sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
1960+
1961+AXNpZw=
1962+`))
1963+)
1964+
1965+func (s *storeTestSuite) makeAssertions(c *C, snapFn, name, snapID, develName, develID string, revision int) {
1966+ dgst, size, err := asserts.SnapFileSHA3_384(snapFn)
1967+ c.Assert(err, IsNil)
1968+
1969+ info := essentialInfo{
1970+ Name: name,
1971+ SnapID: snapID,
1972+ DeveloperID: develID,
1973+ DevelName: develName,
1974+ Revision: revision,
1975+ Size: size,
1976+ Digest: dgst,
1977+ }
1978+
1979+ f, err := os.OpenFile(filepath.Join(s.store.assertDir, snapID+".fake.snap-declaration"), os.O_CREATE|os.O_WRONLY, 0644)
1980+ c.Assert(err, IsNil)
1981+ err = tSnapDecl.Execute(f, info)
1982+ c.Assert(err, IsNil)
1983+
1984+ f, err = os.OpenFile(filepath.Join(s.store.assertDir, dgst+".fake.snap-revision"), os.O_CREATE|os.O_WRONLY, 0644)
1985+ c.Assert(err, IsNil)
1986+ err = tSnapRev.Execute(f, info)
1987+ c.Assert(err, IsNil)
1988+
1989+ f, err = os.OpenFile(filepath.Join(s.store.assertDir, develID+".fake.account"), os.O_CREATE|os.O_WRONLY, 0644)
1990+ c.Assert(err, IsNil)
1991+ err = tAccount.Execute(f, info)
1992+ c.Assert(err, IsNil)
1993+}
1994+
1995+func (s *storeTestSuite) TestMakeTestSnap(c *C) {
1996+ snapFn := s.makeTestSnap(c, "name: foo\nversion: 1")
1997+ c.Assert(osutil.FileExists(snapFn), Equals, true)
1998+ c.Assert(snapFn, Equals, filepath.Join(s.store.blobDir, "foo_1_all.snap"))
1999+}
2000+
2001+func (s *storeTestSuite) TestCollectSnaps(c *C) {
2002+ s.makeTestSnap(c, "name: foo\nversion: 1")
2003+
2004+ snaps, err := s.store.collectSnaps()
2005+ c.Assert(err, IsNil)
2006+ c.Assert(snaps, DeepEquals, map[string]string{
2007+ "foo": filepath.Join(s.store.blobDir, "foo_1_all.snap"),
2008+ })
2009+}
2010+
2011+func (s *storeTestSuite) TestSnapDownloadByFullname(c *C) {
2012+ s.makeTestSnap(c, "name: foo\nversion: 1")
2013+
2014+ resp, err := s.StoreGet("/download/foo_1_all.snap")
2015+ c.Assert(err, IsNil)
2016+ defer resp.Body.Close()
2017+
2018+ c.Assert(resp.StatusCode, Equals, 200)
2019+}
2020+
2021+const (
2022+ exampleSnapRev = `type: snap-revision
2023+authority-id: canonical
2024+snap-sha3-384: QlqR0uAWEAWF5Nwnzj5kqmmwFslYPu1IL16MKtLKhwhv0kpBv5wKZ_axf_nf_2cL
2025+snap-id: snap-id-1
2026+snap-size: 999
2027+snap-revision: 36
2028+developer-id: developer1
2029+timestamp: 2016-08-19T19:19:19Z
2030+sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
2031+
2032+AXNpZw=`
2033+)
2034+
2035+func (s *storeTestSuite) TestAssertionsEndpointPreloaded(c *C) {
2036+ // something preloaded
2037+ resp, err := s.StoreGet(`/api/v1/snaps/assertions/account/testrootorg`)
2038+ c.Assert(err, IsNil)
2039+ defer resp.Body.Close()
2040+
2041+ c.Assert(resp.StatusCode, Equals, 200)
2042+ c.Check(resp.Header.Get("Content-Type"), Equals, "application/x.ubuntu.assertion")
2043+
2044+ body, err := ioutil.ReadAll(resp.Body)
2045+ c.Assert(err, IsNil)
2046+ c.Check(string(body), Equals, string(asserts.Encode(systestkeys.TestRootAccount)))
2047+}
2048+
2049+func (s *storeTestSuite) TestAssertionsEndpointFromAssertsDir(c *C) {
2050+ // something put in the assertion directory
2051+ a, err := asserts.Decode([]byte(exampleSnapRev))
2052+ c.Assert(err, IsNil)
2053+ rev := a.(*asserts.SnapRevision)
2054+
2055+ err = ioutil.WriteFile(filepath.Join(s.store.assertDir, "foo_36.snap-revision"), []byte(exampleSnapRev), 0655)
2056+ c.Assert(err, IsNil)
2057+
2058+ resp, err := s.StoreGet(`/api/v1/snaps/assertions/snap-revision/` + rev.SnapSHA3_384())
2059+ c.Assert(err, IsNil)
2060+ defer resp.Body.Close()
2061+
2062+ c.Assert(resp.StatusCode, Equals, 200)
2063+ body, err := ioutil.ReadAll(resp.Body)
2064+ c.Assert(err, IsNil)
2065+ c.Check(string(body), Equals, exampleSnapRev)
2066+}
2067+
2068+func (s *storeTestSuite) TestAssertionsEndpointNotFound(c *C) {
2069+ // something not found
2070+ resp, err := s.StoreGet(`/api/v1/snaps/assertions/account/not-an-account-id`)
2071+ c.Assert(err, IsNil)
2072+ defer resp.Body.Close()
2073+
2074+ c.Assert(resp.StatusCode, Equals, 404)
2075+
2076+ dec := json.NewDecoder(resp.Body)
2077+ var respObj map[string]interface{}
2078+ err = dec.Decode(&respObj)
2079+ c.Assert(err, IsNil)
2080+ c.Check(respObj["status"], Equals, float64(404))
2081+}
2082+
2083+func (s *storeTestSuite) TestSnapActionEndpoint(c *C) {
2084+ snapFn := s.makeTestSnap(c, "name: test-snapd-tools\nversion: 1")
2085+
2086+ resp, err := s.StorePostJSON("/v2/snaps/refresh", []byte(`{
2087+"context": [{"instance-key":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","snap-id":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","tracking-channel":"stable","revision":1}],
2088+"actions": [{"action":"refresh","instance-key":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","snap-id":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw"}]
2089+}`))
2090+ c.Assert(err, IsNil)
2091+ defer resp.Body.Close()
2092+
2093+ c.Assert(resp.StatusCode, Equals, 200)
2094+ var body struct {
2095+ Results []map[string]interface{}
2096+ }
2097+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
2098+ c.Check(body.Results, HasLen, 1)
2099+ sha3_384, size := getSha(snapFn)
2100+ c.Check(body.Results[0], DeepEquals, map[string]interface{}{
2101+ "result": "refresh",
2102+ "instance-key": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
2103+ "snap-id": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
2104+ "name": "test-snapd-tools",
2105+ "snap": map[string]interface{}{
2106+ "architectures": []interface{}{"all"},
2107+ "snap-id": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
2108+ "name": "test-snapd-tools",
2109+ "publisher": map[string]interface{}{
2110+ "username": "canonical",
2111+ "id": "canonical",
2112+ },
2113+ "download": map[string]interface{}{
2114+ "url": s.store.URL() + "/download/test-snapd-tools_1_all.snap",
2115+ "sha3-384": sha3_384,
2116+ "size": float64(size),
2117+ },
2118+ "version": "1",
2119+ "revision": float64(424242),
2120+ },
2121+ })
2122+}
2123+
2124+func (s *storeTestSuite) TestSnapActionEndpointWithAssertions(c *C) {
2125+ snapFn := s.makeTestSnap(c, "name: foo\nversion: 10")
2126+ s.makeAssertions(c, snapFn, "foo", "xidididididididididididididididid", "foo-devel", "foo-devel-id", 99)
2127+
2128+ resp, err := s.StorePostJSON("/v2/snaps/refresh", []byte(`{
2129+"context": [{"instance-key":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","snap-id":"xidididididididididididididididid","tracking-channel":"stable","revision":1}],
2130+"actions": [{"action":"refresh","instance-key":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","snap-id":"xidididididididididididididididid"}]
2131+}`))
2132+ c.Assert(err, IsNil)
2133+ defer resp.Body.Close()
2134+
2135+ c.Assert(resp.StatusCode, Equals, 200)
2136+ var body struct {
2137+ Results []map[string]interface{}
2138+ }
2139+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
2140+ c.Check(body.Results, HasLen, 1)
2141+ sha3_384, size := getSha(snapFn)
2142+ c.Check(body.Results[0], DeepEquals, map[string]interface{}{
2143+ "result": "refresh",
2144+ "instance-key": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
2145+ "snap-id": "xidididididididididididididididid",
2146+ "name": "foo",
2147+ "snap": map[string]interface{}{
2148+ "architectures": []interface{}{"all"},
2149+ "snap-id": "xidididididididididididididididid",
2150+ "name": "foo",
2151+ "publisher": map[string]interface{}{
2152+ "username": "foo-devel",
2153+ "id": "foo-devel-id",
2154+ },
2155+ "download": map[string]interface{}{
2156+ "url": s.store.URL() + "/download/foo_10_all.snap",
2157+ "sha3-384": sha3_384,
2158+ "size": float64(size),
2159+ },
2160+ "version": "10",
2161+ "revision": float64(99),
2162+ },
2163+ })
2164+}
2165+
2166+func (s *storeTestSuite) TestSnapActionEndpointRefreshAll(c *C) {
2167+ snapFn := s.makeTestSnap(c, "name: test-snapd-tools\nversion: 1")
2168+
2169+ resp, err := s.StorePostJSON("/v2/snaps/refresh", []byte(`{
2170+"context": [{"instance-key":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","snap-id":"eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw","tracking-channel":"stable","revision":1}],
2171+"actions": [{"action":"refresh-all"}]
2172+}`))
2173+ c.Assert(err, IsNil)
2174+ defer resp.Body.Close()
2175+
2176+ c.Assert(resp.StatusCode, Equals, 200)
2177+ var body struct {
2178+ Results []map[string]interface{}
2179+ }
2180+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
2181+ c.Check(body.Results, HasLen, 1)
2182+ sha3_384, size := getSha(snapFn)
2183+ c.Check(body.Results[0], DeepEquals, map[string]interface{}{
2184+ "result": "refresh",
2185+ "instance-key": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
2186+ "snap-id": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
2187+ "name": "test-snapd-tools",
2188+ "snap": map[string]interface{}{
2189+ "architectures": []interface{}{"all"},
2190+ "snap-id": "eFe8BTR5L5V9F7yHeMAPxkEr2NdUXMtw",
2191+ "name": "test-snapd-tools",
2192+ "publisher": map[string]interface{}{
2193+ "username": "canonical",
2194+ "id": "canonical",
2195+ },
2196+ "download": map[string]interface{}{
2197+ "url": s.store.URL() + "/download/test-snapd-tools_1_all.snap",
2198+ "sha3-384": sha3_384,
2199+ "size": float64(size),
2200+ },
2201+ "version": "1",
2202+ "revision": float64(424242),
2203+ },
2204+ })
2205+}
2206+
2207+func (s *storeTestSuite) TestSnapActionEndpointWithAssertionsInstall(c *C) {
2208+ snapFn := s.makeTestSnap(c, "name: foo\nversion: 10")
2209+ s.makeAssertions(c, snapFn, "foo", "xidididididididididididididididid", "foo-devel", "foo-devel-id", 99)
2210+
2211+ resp, err := s.StorePostJSON("/v2/snaps/refresh", []byte(`{
2212+"context": [],
2213+"actions": [{"action":"install","instance-key":"foo","name":"foo"}]
2214+}`))
2215+ c.Assert(err, IsNil)
2216+ defer resp.Body.Close()
2217+
2218+ c.Assert(resp.StatusCode, Equals, 200)
2219+ var body struct {
2220+ Results []map[string]interface{}
2221+ }
2222+ c.Assert(json.NewDecoder(resp.Body).Decode(&body), IsNil)
2223+ c.Check(body.Results, HasLen, 1)
2224+ sha3_384, size := getSha(snapFn)
2225+ c.Check(body.Results[0], DeepEquals, map[string]interface{}{
2226+ "result": "install",
2227+ "instance-key": "foo",
2228+ "snap-id": "xidididididididididididididididid",
2229+ "name": "foo",
2230+ "snap": map[string]interface{}{
2231+ "architectures": []interface{}{"all"},
2232+ "snap-id": "xidididididididididididididididid",
2233+ "name": "foo",
2234+ "publisher": map[string]interface{}{
2235+ "username": "foo-devel",
2236+ "id": "foo-devel-id",
2237+ },
2238+ "download": map[string]interface{}{
2239+ "url": s.store.URL() + "/download/foo_10_all.snap",
2240+ "sha3-384": sha3_384,
2241+ "size": float64(size),
2242+ },
2243+ "version": "10",
2244+ "revision": float64(99),
2245+ },
2246+ })
2247+}
2248diff --git a/tests/lib/files.sh b/tests/lib/files.sh
2249new file mode 100644
2250index 0000000..5187695
2251--- /dev/null
2252+++ b/tests/lib/files.sh
2253@@ -0,0 +1,75 @@
2254+#!/bin/bash
2255+
2256+wait_for_file() {
2257+ the_file="$1"
2258+ iters="$2"
2259+ sleep_time="$3"
2260+
2261+ for _ in $(seq "$iters"); do
2262+ if [ -f "$the_file" ]; then
2263+ return 0
2264+ fi
2265+ sleep "$sleep_time"
2266+ done
2267+ return 1
2268+}
2269+
2270+ensure_dir_exists() {
2271+ dir="$1"
2272+ if ! [ -d "$dir" ]; then
2273+ mkdir -p "$dir"
2274+ touch "$dir.fake"
2275+ fi
2276+}
2277+
2278+ensure_dir_exists_backup_real() {
2279+ dir="$1"
2280+ if [ -d "$dir" ]; then
2281+ mv "$dir" "$dir.back"
2282+ fi
2283+ mkdir -p "$dir"
2284+ touch "$dir.fake"
2285+}
2286+
2287+clean_dir() {
2288+ dir="$1"
2289+ if [ -f "$dir.fake" ]; then
2290+ rm -rf "$dir"
2291+ rm -f "$dir.fake"
2292+ fi
2293+ if [ -d "$dir.back" ]; then
2294+ mv "$dir.back" "$dir"
2295+ fi
2296+}
2297+
2298+ensure_file_exists() {
2299+ file="$1"
2300+ if ! [ -f "$file" ]; then
2301+ touch "$file"
2302+ touch "$file.fake"
2303+ fi
2304+}
2305+
2306+ensure_file_exists_backup_real() {
2307+ file="$1"
2308+ if [ -f "$file" ]; then
2309+ mv "$file" "$file.back"
2310+ fi
2311+ # ensure the parent dir is available
2312+ if [ ! -d "$(dirname $file)" ]; then
2313+ mkdir -p "$(dirname $file)"
2314+ fi
2315+ touch "$file"
2316+ touch "$file.fake"
2317+}
2318+
2319+clean_file() {
2320+ file="$1"
2321+ if [ -f "$file.fake" ]; then
2322+ rm -f "$file"
2323+ rm -f "$file.fake"
2324+ fi
2325+ if [ -f "$file.back" ]; then
2326+ mv "$file.back" "$file"
2327+ fi
2328+}
2329diff --git a/tests/lib/journalctl.sh b/tests/lib/journalctl.sh
2330new file mode 100644
2331index 0000000..4b21370
2332--- /dev/null
2333+++ b/tests/lib/journalctl.sh
2334@@ -0,0 +1,58 @@
2335+#!/bin/bash
2336+
2337+# shellcheck source=tests/lib/state.sh
2338+. "$TESTSLIB/state.sh"
2339+
2340+# This file contains all the cursors used for the different tests
2341+JOURNALCTL_CURSOR_FILE="$RUNTIME_STATE_PATH"/journalctl_cursor
2342+
2343+get_last_journalctl_cursor(){
2344+ journalctl --output=export -n1 | grep --binary-files=text -o '__CURSOR=.*' | sed -e 's/^__CURSOR=//'
2345+}
2346+
2347+start_new_journalctl_log(){
2348+ echo "New test starts here - $SPREAD_JOB" | systemd-cat -t snapd-test
2349+ cursor=$(get_last_journalctl_cursor)
2350+ if [ -z "$cursor" ]; then
2351+ echo "Empty journalctl cursor, exiting..."
2352+ exit 1
2353+ else
2354+ echo "$SPREAD_JOB " >> "$JOURNALCTL_CURSOR_FILE"
2355+ echo "$cursor" >> "$JOURNALCTL_CURSOR_FILE"
2356+ fi
2357+}
2358+
2359+check_journalctl_ready(){
2360+ marker="test-${RANDOM}${RANDOM}"
2361+ echo "Running test: $marker" | systemd-cat -t snapd-test
2362+ if check_journalctl_log "$marker"; then
2363+ return 0
2364+ fi
2365+ echo "Test id not found in journalctl, exiting..."
2366+ exit 1
2367+}
2368+
2369+check_journalctl_log(){
2370+ expression=$1
2371+ shift
2372+ for _ in $(seq 20); do
2373+ log=$(get_journalctl_log "$@")
2374+ if echo "$log" | grep -q -E "$expression"; then
2375+ return 0
2376+ fi
2377+ echo "Match failed, retrying"
2378+ sleep .5
2379+ done
2380+ return 1
2381+}
2382+
2383+get_journalctl_log(){
2384+ cursor=$(tail -n1 "$JOURNALCTL_CURSOR_FILE")
2385+ get_journalctl_log_from_cursor "$cursor" "$@"
2386+}
2387+
2388+get_journalctl_log_from_cursor(){
2389+ cursor=$1
2390+ shift
2391+ journalctl "$@" --cursor "$cursor"
2392+}
2393diff --git a/tests/lib/list-interfaces.go b/tests/lib/list-interfaces.go
2394new file mode 100644
2395index 0000000..6687a27
2396--- /dev/null
2397+++ b/tests/lib/list-interfaces.go
2398@@ -0,0 +1,10 @@
2399+package main
2400+
2401+import "fmt"
2402+import "github.com/snapcore/snapd/interfaces/builtin"
2403+
2404+func main() {
2405+ for _, iface := range builtin.Interfaces() {
2406+ fmt.Printf("%s\n", iface.Name())
2407+ }
2408+}
2409diff --git a/tests/lib/mkpinentry.sh b/tests/lib/mkpinentry.sh
2410new file mode 100755
2411index 0000000..4641deb
2412--- /dev/null
2413+++ b/tests/lib/mkpinentry.sh
2414@@ -0,0 +1,21 @@
2415+#!/bin/bash
2416+
2417+if gpg --version | MATCH 'gpg \(GnuPG\) 1.'; then
2418+ echo "fake gpg pinentry not used for gpg v1"
2419+else
2420+ echo "setup fake gpg pinentry environment for gpg v2 or higher"
2421+ case "$SPREAD_SYSTEM" in
2422+ opensuse-*)
2423+ mkdir -p ~/.gnupg
2424+ echo pinentry-program "$TESTSLIB/pinentry-fake.sh" > ~/.gnupg/gpg-agent.conf
2425+ ;;
2426+ *)
2427+ mkdir -p ~/.snap/gnupg/
2428+ # It is just created once by gpg-agent, then if this dir does not exist gpg will
2429+ # fail to create the key
2430+ mkdir -p ~/.snap/gnupg/private-keys-v1.d
2431+ echo pinentry-program "$TESTSLIB/pinentry-fake.sh" > ~/.snap/gnupg/gpg-agent.conf
2432+ chmod -R go-rwx ~/.snap
2433+ ;;
2434+ esac
2435+fi
2436diff --git a/tests/lib/names.sh b/tests/lib/names.sh
2437new file mode 100644
2438index 0000000..e8e1ebc
2439--- /dev/null
2440+++ b/tests/lib/names.sh
2441@@ -0,0 +1,10 @@
2442+#!/bin/bash
2443+# shellcheck disable=SC2034
2444+
2445+gadget_name=$(snap list | grep 'gadget$' | awk '{ print $1 }')
2446+kernel_name=$(snap list | grep 'kernel$' | awk '{ print $1 }')
2447+
2448+core_name="$(snap known model | awk '/^base: / { print $2 }' || true)"
2449+if [ -z "$core_name" ]; then
2450+ core_name="core"
2451+fi
2452diff --git a/tests/lib/nested.sh b/tests/lib/nested.sh
2453new file mode 100644
2454index 0000000..fdffb7b
2455--- /dev/null
2456+++ b/tests/lib/nested.sh
2457@@ -0,0 +1,68 @@
2458+#!/bin/bash
2459+
2460+# shellcheck source=tests/lib/systemd.sh
2461+. "$TESTSLIB"/systemd.sh
2462+
2463+wait_for_ssh(){
2464+ retry=300
2465+ while ! execute_remote true; do
2466+ retry=$(( retry - 1 ))
2467+ if [ $retry -le 0 ]; then
2468+ echo "Timed out waiting for ssh. Aborting!"
2469+ exit 1
2470+ fi
2471+ sleep 1
2472+ done
2473+}
2474+
2475+prepare_ssh(){
2476+ execute_remote "sudo adduser --extrausers --quiet --disabled-password --gecos '' test"
2477+ execute_remote "echo test:ubuntu | sudo chpasswd"
2478+ execute_remote "echo 'test ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/test-user"
2479+}
2480+
2481+create_assertions_disk(){
2482+ dd if=/dev/null of=assertions.disk bs=1M seek=1
2483+ mkfs.ext4 -F assertions.disk
2484+ mkdir /mnt/assertions
2485+ mount -t ext4 -o loop assertions.disk /mnt/assertions
2486+ cp "$TESTSLIB/assertions/auto-import.assert" /mnt/assertions
2487+ umount /mnt/assertions && rm -rf /mnt/assertions
2488+}
2489+
2490+create_nested_core_vm(){
2491+ # determine arch related vars
2492+ case "$NESTED_ARCH" in
2493+ amd64)
2494+ QEMU="$(command -v qemu-system-x86_64)"
2495+ ;;
2496+ i386)
2497+ QEMU="$(command -v qemu-system-i386)"
2498+ ;;
2499+ *)
2500+ echo "unsupported architecture"
2501+ exit 1
2502+ ;;
2503+ esac
2504+
2505+ # create ubuntu-core image
2506+ mkdir -p /tmp/work-dir
2507+ /snap/bin/ubuntu-image --image-size 3G "$TESTSLIB/assertions/nested-${NESTED_ARCH}.model" --channel "$CORE_CHANNEL" --output ubuntu-core.img
2508+ mv ubuntu-core.img /tmp/work-dir
2509+
2510+ create_assertions_disk
2511+
2512+ systemd_create_and_start_unit nested-vm "${QEMU} -m 1024 -nographic -net nic,model=virtio -net user,hostfwd=tcp::8022-:22 -drive file=/tmp/work-dir/ubuntu-core.img,if=virtio,cache=none -drive file=${PWD}/assertions.disk,if=virtio,cache=none"
2513+
2514+ wait_for_ssh
2515+ prepare_ssh
2516+}
2517+
2518+destroy_nested_core_vm(){
2519+ systemd_stop_and_destroy_unit nested-vm
2520+ rm -rf /tmp/work-dir
2521+}
2522+
2523+execute_remote(){
2524+ sshpass -p ubuntu ssh -p 8022 -q -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no user1@localhost "$*"
2525+}
2526diff --git a/tests/lib/network.sh b/tests/lib/network.sh
2527new file mode 100644
2528index 0000000..d60fe3f
2529--- /dev/null
2530+++ b/tests/lib/network.sh
2531@@ -0,0 +1,34 @@
2532+#!/bin/bash
2533+
2534+get_default_iface(){
2535+ ip route get 8.8.8.8 | awk '{ print $5; exit }'
2536+}
2537+
2538+wait_listen_port(){
2539+ PORT="$1"
2540+
2541+ for _ in $(seq 120); do
2542+ if ss -lnt | grep -Pq "LISTEN.*?:$PORT +.*?\\n*"; then
2543+ break
2544+ fi
2545+ sleep 0.5
2546+ done
2547+
2548+ # Ensure we really have the listen port, this will fail with an
2549+ # exit code if the port is not available.
2550+ ss -lnt | grep -Pq "LISTEN.*?:$PORT +.*?\\n*"
2551+}
2552+
2553+make_network_service() {
2554+ SERVICE_NAME="$1"
2555+ SERVICE_FILE="$2"
2556+ PORT="$3"
2557+
2558+ #shellcheck source=tests/lib/systemd.sh
2559+ . "$TESTSLIB"/systemd.sh
2560+
2561+ printf '#!/bin/sh -e\nwhile true; do printf '\''HTTP/1.1 200 OK\\n\\nok\\n'\'' | nc -l -p %s -w 1; done' "$PORT" > "$SERVICE_FILE"
2562+ chmod a+x "$SERVICE_FILE"
2563+ systemd_create_and_start_unit "$SERVICE_NAME" "$(readlink -f "$SERVICE_FILE")"
2564+ wait_listen_port "$PORT"
2565+}
2566diff --git a/tests/lib/os-release.16 b/tests/lib/os-release.16
2567new file mode 100644
2568index 0000000..6e65d69
2569--- /dev/null
2570+++ b/tests/lib/os-release.16
2571@@ -0,0 +1,7 @@
2572+NAME="Ubuntu Core"
2573+VERSION="16"
2574+ID=ubuntu-core
2575+PRETTY_NAME="Ubuntu Core 16"
2576+VERSION_ID="16"
2577+HOME_URL="http://www.snapcraft.io/"
2578+BUG_REPORT_URL="http://bugs.launchpad.net/snappy/"
2579diff --git a/tests/lib/pinentry-fake.sh b/tests/lib/pinentry-fake.sh
2580new file mode 100755
2581index 0000000..2af7576
2582--- /dev/null
2583+++ b/tests/lib/pinentry-fake.sh
2584@@ -0,0 +1,20 @@
2585+#!/bin/bash
2586+
2587+set -e
2588+
2589+echo "OK Pleased to meet you"
2590+while true; do
2591+ read -r line
2592+ case $line in
2593+ GETPIN)
2594+ echo "D pass"
2595+ echo "OK"
2596+ ;;
2597+ BYE)
2598+ exit 0
2599+ ;;
2600+ *)
2601+ echo "OK I'm not very smart"
2602+ ;;
2603+ esac
2604+done
2605diff --git a/tests/lib/pkgdb.sh b/tests/lib/pkgdb.sh
2606new file mode 100755
2607index 0000000..4b4df19
2608--- /dev/null
2609+++ b/tests/lib/pkgdb.sh
2610@@ -0,0 +1,733 @@
2611+#!/bin/bash
2612+
2613+# shellcheck source=tests/lib/quiet.sh
2614+. "$TESTSLIB/quiet.sh"
2615+
2616+debian_name_package() {
2617+ for i in "$@"; do
2618+ case "$i" in
2619+ man)
2620+ echo "man-db"
2621+ ;;
2622+ *)
2623+ echo "$i"
2624+ ;;
2625+ esac
2626+ done
2627+}
2628+
2629+ubuntu_14_04_name_package() {
2630+ for i in "$@"; do
2631+ case "$i" in
2632+ printer-driver-cups-pdf)
2633+ echo "cups-pdf"
2634+ ;;
2635+ *)
2636+ debian_name_package "$i"
2637+ ;;
2638+ esac
2639+ done
2640+}
2641+
2642+fedora_name_package() {
2643+ for i in "$@"; do
2644+ case "$i" in
2645+ openvswitch-switch)
2646+ echo "openvswitch"
2647+ ;;
2648+ printer-driver-cups-pdf)
2649+ echo "cups-pdf"
2650+ ;;
2651+ *)
2652+ echo "$i"
2653+ ;;
2654+ esac
2655+ done
2656+}
2657+
2658+amazon_name_package() {
2659+ for i in "$@"; do
2660+ case "$i" in
2661+ xdelta3)
2662+ echo "xdelta"
2663+ ;;
2664+ *)
2665+ echo "$i"
2666+ ;;
2667+ esac
2668+ done
2669+}
2670+
2671+opensuse_name_package() {
2672+ for i in "$@"; do
2673+ case "$i" in
2674+ python3-yaml)
2675+ echo "python3-PyYAML"
2676+ ;;
2677+ dbus-x11)
2678+ echo "dbus-1-x11"
2679+ ;;
2680+ printer-driver-cups-pdf)
2681+ echo "cups-pdf"
2682+ ;;
2683+ *)
2684+ echo "$i"
2685+ ;;
2686+ esac
2687+ done
2688+}
2689+
2690+arch_name_package() {
2691+ case "$1" in
2692+ python3-yaml)
2693+ echo "python-yaml"
2694+ ;;
2695+ dbus-x11)
2696+ # no separate dbus-x11 package in arch
2697+ echo "dbus"
2698+ ;;
2699+ printer-driver-cups-pdf)
2700+ echo "cups-pdf"
2701+ ;;
2702+ openvswitch-switch)
2703+ echo "openvswitch"
2704+ ;;
2705+ man)
2706+ echo "man-db"
2707+ ;;
2708+ *)
2709+ echo "$1"
2710+ ;;
2711+ esac
2712+}
2713+
2714+distro_name_package() {
2715+ case "$SPREAD_SYSTEM" in
2716+ ubuntu-14.04-*)
2717+ ubuntu_14_04_name_package "$@"
2718+ ;;
2719+ ubuntu-*|debian-*)
2720+ debian_name_package "$@"
2721+ ;;
2722+ fedora-*)
2723+ fedora_name_package "$@"
2724+ ;;
2725+ amazon-*)
2726+ amazon_name_package "$@"
2727+ ;;
2728+ opensuse-*)
2729+ opensuse_name_package "$@"
2730+ ;;
2731+ arch-*)
2732+ arch_name_package "$1"
2733+ ;;
2734+ *)
2735+ echo "ERROR: Unsupported distribution $SPREAD_SYSTEM"
2736+ exit 1
2737+ ;;
2738+ esac
2739+}
2740+
2741+distro_install_local_package() {
2742+ allow_downgrades=false
2743+ while [ -n "$1" ]; do
2744+ case "$1" in
2745+ --allow-downgrades)
2746+ allow_downgrades=true
2747+ shift
2748+ ;;
2749+ *)
2750+ break
2751+ esac
2752+ done
2753+
2754+ case "$SPREAD_SYSTEM" in
2755+ ubuntu-14.04-*|debian-*)
2756+ # relying on dpkg as apt(-get) does not support installation from local files in trusty.
2757+ dpkg -i --force-depends --auto-deconfigure --force-depends-version "$@"
2758+ apt-get -f install -y
2759+ ;;
2760+ ubuntu-*)
2761+ flags="-y"
2762+ if [ "$allow_downgrades" = "true" ]; then
2763+ flags="$flags --allow-downgrades"
2764+ fi
2765+ # shellcheck disable=SC2086
2766+ apt install $flags "$@"
2767+ ;;
2768+ fedora-*)
2769+ quiet dnf -y install "$@"
2770+ ;;
2771+ amazon-*)
2772+ quiet yum -y localinstall "$@"
2773+ ;;
2774+ opensuse-*)
2775+ quiet rpm -i "$@"
2776+ ;;
2777+ arch-*)
2778+ pacman -U --noconfirm "$@"
2779+ ;;
2780+ *)
2781+ echo "ERROR: Unsupported distribution $SPREAD_SYSTEM"
2782+ exit 1
2783+ ;;
2784+ esac
2785+}
2786+
2787+distro_install_package() {
2788+ # Parse additional arguments; once we find the first unknown
2789+ # part we break argument parsing and process all further
2790+ # arguments as package names.
2791+ APT_FLAGS=
2792+ DNF_FLAGS=
2793+ YUM_FLAGS=
2794+ ZYPPER_FLAGS=
2795+ while [ -n "$1" ]; do
2796+ case "$1" in
2797+ --no-install-recommends)
2798+ APT_FLAGS="$APT_FLAGS --no-install-recommends"
2799+ DNF_FLAGS="$DNF_FLAGS --setopt=install_weak_deps=False"
2800+ ZYPPER_FLAGS="$ZYPPER_FLAGS --no-recommends"
2801+ # TODO no way to set this for yum?
2802+ shift
2803+ ;;
2804+ *)
2805+ break
2806+ ;;
2807+ esac
2808+ done
2809+
2810+ # ensure systemd is up-to-date, if there is a mismatch libudev-dev
2811+ # will fail to install because the poor apt resolver does not get it
2812+ case "$SPREAD_SYSTEM" in
2813+ ubuntu-*|debian-*)
2814+ if [[ "$*" =~ "libudev-dev" ]]; then
2815+ apt-get install -y --only-upgrade systemd
2816+ fi
2817+ ;;
2818+ esac
2819+
2820+ # fix dependency issue where libp11-kit0 needs to be downgraded to
2821+ # install gnome-keyring
2822+ case "$SPREAD_SYSTEM" in
2823+ debian-9-*)
2824+ if [[ "$*" =~ "gnome-keyring" ]]; then
2825+ apt-get remove -y libp11-kit0
2826+ fi
2827+ ;;
2828+ esac
2829+
2830+ # shellcheck disable=SC2207
2831+ pkg_names=($(
2832+ for pkg in "$@" ; do
2833+ package_name=$(distro_name_package "$pkg")
2834+ # When we could not find a different package name for the distribution
2835+ # we're running on we try the package name given as last attempt
2836+ if [ -z "$package_name" ]; then
2837+ package_name="$pkg"
2838+ fi
2839+ echo "$package_name"
2840+ done
2841+ ))
2842+
2843+ case "$SPREAD_SYSTEM" in
2844+ ubuntu-*|debian-*)
2845+ # shellcheck disable=SC2086
2846+ quiet apt-get install $APT_FLAGS -y "${pkg_names[@]}"
2847+ ;;
2848+ fedora-*)
2849+ # shellcheck disable=SC2086
2850+ quiet dnf -y --refresh install $DNF_FLAGS "${pkg_names[@]}"
2851+ ;;
2852+ amazon-*)
2853+ # shellcheck disable=SC2086
2854+ quiet yum -y install $YUM_FLAGS "${pkg_names[@]}"
2855+ ;;
2856+ opensuse-*)
2857+ # shellcheck disable=SC2086
2858+ quiet zypper install -y $ZYPPER_FLAGS "${pkg_names[@]}"
2859+ ;;
2860+ arch-*)
2861+ # shellcheck disable=SC2086
2862+ pacman -Suq --needed --noconfirm "${pkg_names[@]}"
2863+ ;;
2864+ *)
2865+ echo "ERROR: Unsupported distribution $SPREAD_SYSTEM"
2866+ exit 1
2867+ ;;
2868+ esac
2869+}
2870+
2871+distro_purge_package() {
2872+ # shellcheck disable=SC2046
2873+ set -- $(
2874+ for pkg in "$@" ; do
2875+ package_name=$(distro_name_package "$pkg")
2876+ # When we could not find a different package name for the distribution
2877+ # we're running on we try the package name given as last attempt
2878+ if [ -z "$package_name" ]; then
2879+ package_name="$pkg"
2880+ fi
2881+ echo "$package_name"
2882+ done
2883+ )
2884+
2885+ case "$SPREAD_SYSTEM" in
2886+ ubuntu-*|debian-*)
2887+ quiet apt-get remove -y --purge -y "$@"
2888+ ;;
2889+ fedora-*)
2890+ quiet dnf -y remove "$@"
2891+ quiet dnf clean all
2892+ ;;
2893+ amazon-*)
2894+ quiet yum -y remove "$@"
2895+ ;;
2896+ opensuse-*)
2897+ quiet zypper remove -y "$@"
2898+ ;;
2899+ arch-*)
2900+ pacman -Rnsc --noconfirm "$@"
2901+ ;;
2902+ *)
2903+ echo "ERROR: Unsupported distribution $SPREAD_SYSTEM"
2904+ exit 1
2905+ ;;
2906+ esac
2907+}
2908+
2909+distro_update_package_db() {
2910+ case "$SPREAD_SYSTEM" in
2911+ ubuntu-*|debian-*)
2912+ quiet apt-get update
2913+ ;;
2914+ fedora-*)
2915+ quiet dnf clean all
2916+ quiet dnf makecache
2917+ ;;
2918+ amazon-*)
2919+ quiet yum clean all
2920+ quiet yum makecache
2921+ ;;
2922+ opensuse-*)
2923+ quiet zypper --gpg-auto-import-keys refresh
2924+ ;;
2925+ arch-*)
2926+ pacman -Syq
2927+ ;;
2928+ *)
2929+ echo "ERROR: Unsupported distribution $SPREAD_SYSTEM"
2930+ exit 1
2931+ ;;
2932+ esac
2933+}
2934+
2935+distro_clean_package_cache() {
2936+ case "$SPREAD_SYSTEM" in
2937+ ubuntu-*|debian-*)
2938+ quiet apt-get clean
2939+ ;;
2940+ fedora-*)
2941+ dnf clean all
2942+ ;;
2943+ amazon-*)
2944+ yum clean all
2945+ ;;
2946+ opensuse-*)
2947+ zypper -q clean --all
2948+ ;;
2949+ arch-*)
2950+ pacman -Sccq --noconfirm
2951+ ;;
2952+ *)
2953+ echo "ERROR: Unsupported distribution $SPREAD_SYSTEM"
2954+ exit 1
2955+ ;;
2956+ esac
2957+}
2958+
2959+distro_auto_remove_packages() {
2960+ case "$SPREAD_SYSTEM" in
2961+ ubuntu-*|debian-*)
2962+ quiet apt-get -y autoremove
2963+ ;;
2964+ fedora-*)
2965+ quiet dnf -y autoremove
2966+ ;;
2967+ amazon-*)
2968+ quiet yum -y autoremove
2969+ ;;
2970+ opensuse-*)
2971+ ;;
2972+ arch-*)
2973+ ;;
2974+ *)
2975+ echo "ERROR: Unsupported distribution '$SPREAD_SYSTEM'"
2976+ exit 1
2977+ ;;
2978+ esac
2979+}
2980+
2981+distro_query_package_info() {
2982+ case "$SPREAD_SYSTEM" in
2983+ ubuntu-*|debian-*)
2984+ apt-cache policy "$1"
2985+ ;;
2986+ fedora-*)
2987+ dnf info "$1"
2988+ ;;
2989+ amazon-*)
2990+ yum info "$1"
2991+ ;;
2992+ opensuse-*)
2993+ zypper info "$1"
2994+ ;;
2995+ arch-*)
2996+ pacman -Si "$1"
2997+ ;;
2998+ *)
2999+ echo "ERROR: Unsupported distribution '$SPREAD_SYSTEM'"
3000+ exit 1
3001+ ;;
3002+ esac
3003+}
3004+
3005+distro_install_build_snapd(){
3006+ if [ "$SRU_VALIDATION" = "1" ]; then
3007+ apt install -y snapd
3008+ cp /etc/apt/sources.list sources.list.back
3009+ echo "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -c -s)-proposed restricted main multiverse universe" | tee /etc/apt/sources.list -a
3010+ apt update
3011+ apt install -y --only-upgrade snapd
3012+ mv sources.list.back /etc/apt/sources.list
3013+ apt update
3014+ # On trusty we may pull in a new hwe-kernel that is needed to run the
3015+ # snapd tests. We need to reboot to actually run this kernel.
3016+ if [[ "$SPREAD_SYSTEM" = ubuntu-14.04-* ]] && [ "$SPREAD_REBOOT" = 0 ]; then
3017+ REBOOT
3018+ fi
3019+ else
3020+ packages=
3021+ case "$SPREAD_SYSTEM" in
3022+ ubuntu-*|debian-*)
3023+ # shellcheck disable=SC2125
3024+ packages="${GOHOME}"/snapd_*.deb
3025+ ;;
3026+ fedora-*|amazon-*)
3027+ # shellcheck disable=SC2125
3028+ packages="${GOHOME}"/snap-confine*.rpm\ "${GOPATH}"/snapd*.rpm
3029+ ;;
3030+ opensuse-*)
3031+ # shellcheck disable=SC2125
3032+ packages="${GOHOME}"/snapd*.rpm
3033+ ;;
3034+ arch-*)
3035+ # shellcheck disable=SC2125
3036+ packages="${GOHOME}"/snapd*.pkg.tar.xz
3037+ ;;
3038+ *)
3039+ exit 1
3040+ ;;
3041+ esac
3042+
3043+ # shellcheck disable=SC2086
3044+ distro_install_local_package $packages
3045+
3046+ if [[ "$SPREAD_SYSTEM" == arch-* ]]; then
3047+ # Arch policy does not allow calling daemon-reloads in package
3048+ # install scripts
3049+ systemctl daemon-reload
3050+ fi
3051+
3052+ # On some distributions the snapd.socket is not yet automatically
3053+ # enabled as we don't have a systemd present configuration approved
3054+ # by the distribution for it in place yet.
3055+ if ! systemctl is-enabled snapd.socket ; then
3056+ # Can't use --now here as not all distributions we run on support it
3057+ systemctl enable snapd.socket
3058+ systemctl start snapd.socket
3059+ fi
3060+ fi
3061+}
3062+
3063+distro_get_package_extension() {
3064+ case "$SPREAD_SYSTEM" in
3065+ ubuntu-*|debian-*)
3066+ echo "deb"
3067+ ;;
3068+ fedora-*|opensuse-*|amazon-*)
3069+ echo "rpm"
3070+ ;;
3071+ arch-*)
3072+ # default /etc/makepkg.conf setting
3073+ echo "pkg.tar.xz"
3074+ ;;
3075+ esac
3076+}
3077+
3078+pkg_dependencies_ubuntu_generic(){
3079+ echo "
3080+ autoconf
3081+ automake
3082+ autotools-dev
3083+ build-essential
3084+ clang
3085+ curl
3086+ devscripts
3087+ expect
3088+ gdb
3089+ gdebi-core
3090+ git
3091+ indent
3092+ jq
3093+ apparmor-utils
3094+ libapparmor-dev
3095+ libglib2.0-dev
3096+ libseccomp-dev
3097+ libudev-dev
3098+ man
3099+ netcat-openbsd
3100+ pkg-config
3101+ python3-docutils
3102+ udev
3103+ upower
3104+ uuid-runtime
3105+ "
3106+}
3107+
3108+pkg_dependencies_ubuntu_classic(){
3109+ echo "
3110+ avahi-daemon
3111+ cups
3112+ dbus-x11
3113+ gnome-keyring
3114+ jq
3115+ man
3116+ printer-driver-cups-pdf
3117+ python3-yaml
3118+ upower
3119+ weston
3120+ xdg-user-dirs
3121+ xdg-utils
3122+ "
3123+
3124+ case "$SPREAD_SYSTEM" in
3125+ ubuntu-14.04-*)
3126+ pkg_linux_image_extra
3127+ ;;
3128+ ubuntu-16.04-32)
3129+ echo "
3130+ evolution-data-server
3131+ gnome-online-accounts
3132+ "
3133+ pkg_linux_image_extra
3134+ ;;
3135+ ubuntu-16.04-64)
3136+ echo "
3137+ evolution-data-server
3138+ gccgo-6
3139+ gnome-online-accounts
3140+ kpartx
3141+ libvirt-bin
3142+ nfs-kernel-server
3143+ qemu
3144+ x11-utils
3145+ xvfb
3146+ "
3147+ pkg_linux_image_extra
3148+ ;;
3149+ ubuntu-17.10-64)
3150+ pkg_linux_image_extra
3151+ ;;
3152+ ubuntu-18.04-64)
3153+ echo "
3154+ evolution-data-server
3155+ "
3156+ ;;
3157+ ubuntu-*)
3158+ echo "
3159+ squashfs-tools
3160+ "
3161+ ;;
3162+ debian-*)
3163+ echo "
3164+ evolution-data-server
3165+ net-tools
3166+ "
3167+ ;;
3168+ esac
3169+}
3170+
3171+pkg_linux_image_extra (){
3172+ if apt-cache show "linux-image-extra-$(uname -r)" > /dev/null 2>&1; then
3173+ echo "linux-image-extra-$(uname -r)";
3174+ else
3175+ if apt-cache show "linux-modules-extra-$(uname -r)" > /dev/null 2>&1; then
3176+ echo "linux-modules-extra-$(uname -r)";
3177+ else
3178+ echo "cannot find a matching kernel modules package";
3179+ exit 1;
3180+ fi;
3181+ fi
3182+}
3183+
3184+pkg_dependencies_ubuntu_core(){
3185+ echo "
3186+ pollinate
3187+ "
3188+ pkg_linux_image_extra
3189+}
3190+
3191+pkg_dependencies_fedora(){
3192+ echo "
3193+ clang
3194+ curl
3195+ dbus-x11
3196+ evolution-data-server
3197+ expect
3198+ git
3199+ golang
3200+ jq
3201+ iptables-services
3202+ man
3203+ mock
3204+ net-tools
3205+ python3-yaml
3206+ redhat-lsb-core
3207+ rpm-build
3208+ xdg-user-dirs
3209+ "
3210+}
3211+
3212+pkg_dependencies_amazon(){
3213+ echo "
3214+ curl
3215+ dbus-x11
3216+ expect
3217+ git
3218+ golang
3219+ jq
3220+ iptables-services
3221+ man
3222+ mock
3223+ net-tools
3224+ system-lsb-core
3225+ rpm-build
3226+ xdg-user-dirs
3227+ grub2-tools
3228+ nc
3229+ "
3230+}
3231+
3232+pkg_dependencies_opensuse(){
3233+ echo "
3234+ apparmor-profiles
3235+ clang
3236+ curl
3237+ evolution-data-server
3238+ expect
3239+ git
3240+ golang-packaging
3241+ jq
3242+ lsb-release
3243+ man
3244+ python3-yaml
3245+ netcat-openbsd
3246+ osc
3247+ uuidd
3248+ xdg-utils
3249+ xdg-user-dirs
3250+ "
3251+}
3252+
3253+pkg_dependencies_arch(){
3254+ echo "
3255+ base-devel
3256+ bash-completion
3257+ clang
3258+ curl
3259+ evolution-data-server
3260+ expect
3261+ git
3262+ go
3263+ go-tools
3264+ jq
3265+ libseccomp
3266+ libcap
3267+ libx11
3268+ net-tools
3269+ openbsd-netcat
3270+ python
3271+ python-docutils
3272+ python3-yaml
3273+ squashfs-tools
3274+ shellcheck
3275+ strace
3276+ xdg-user-dirs
3277+ xfsprogs
3278+ "
3279+}
3280+
3281+pkg_dependencies(){
3282+ case "$SPREAD_SYSTEM" in
3283+ ubuntu-core-16-*)
3284+ pkg_dependencies_ubuntu_generic
3285+ pkg_dependencies_ubuntu_core
3286+ ;;
3287+ ubuntu-*|debian-*)
3288+ pkg_dependencies_ubuntu_generic
3289+ pkg_dependencies_ubuntu_classic
3290+ ;;
3291+ fedora-*)
3292+ pkg_dependencies_fedora
3293+ ;;
3294+ amazon-*)
3295+ pkg_dependencies_amazon
3296+ ;;
3297+ opensuse-*)
3298+ pkg_dependencies_opensuse
3299+ ;;
3300+ arch-*)
3301+ pkg_dependencies_arch
3302+ ;;
3303+ *)
3304+ ;;
3305+ esac
3306+}
3307+
3308+install_pkg_dependencies(){
3309+ pkgs=$(pkg_dependencies)
3310+ # shellcheck disable=SC2086
3311+ distro_install_package $pkgs
3312+}
3313+
3314+# upgrade distribution and indicate if reboot is needed by outputting 'reboot'
3315+# to stdout
3316+distro_upgrade() {
3317+ case "$SPREAD_SYSTEM" in
3318+ arch-*)
3319+ # Arch does not support partial upgrades. On top of this, the image
3320+ # we are running in may have been built some time ago and we need to
3321+ # upgrade so that the tests are run with the same package versions
3322+ # as the users will have. We basically need to run pacman -Syu.
3323+ # Since there is no way to tell if we can continue after upgrading
3324+ # (eg. the kernel package or systemd got updated ) issue a reboot
3325+ # instead.
3326+ #
3327+ # pacman -Syu --noconfirm on an updated system:
3328+ # :: Synchronizing package databases...
3329+ # core is up to date
3330+ # extra is up to date
3331+ # community is up to date
3332+ # multilib is up to date
3333+ # :: Starting full system upgrade...
3334+ # there is nothing to do <--- needle
3335+ if ! pacman -Syu --noconfirm 2>&1 | grep -q "there is nothing to do" ; then
3336+ echo "reboot"
3337+ fi
3338+ ;;
3339+ *)
3340+ echo "WARNING: distro upgrade not supported on $SPREAD_SYSTEM"
3341+ ;;
3342+ esac
3343+}
3344diff --git a/tests/lib/prepare-restore.sh b/tests/lib/prepare-restore.sh
3345new file mode 100755
3346index 0000000..0c2c9d2
3347--- /dev/null
3348+++ b/tests/lib/prepare-restore.sh
3349@@ -0,0 +1,538 @@
3350+#!/bin/bash
3351+set -x
3352+# NOTE: We must set -e so that any failures coming out of the various
3353+# statements we execute stops the build. The code is not (yet) written to
3354+# handle errors in general.
3355+set -e
3356+# Set pipefail option so that "foo | bar" behaves with fewer surprises by
3357+# failing if foo fails, not just if bar fails.
3358+set -o pipefail
3359+
3360+# shellcheck source=tests/lib/quiet.sh
3361+. "$TESTSLIB/quiet.sh"
3362+
3363+# XXX: boot.sh has side-effects
3364+# shellcheck source=tests/lib/boot.sh
3365+. "$TESTSLIB/boot.sh"
3366+
3367+# XXX: dirs.sh has side-effects
3368+# shellcheck source=tests/lib/dirs.sh
3369+. "$TESTSLIB/dirs.sh"
3370+
3371+# shellcheck source=tests/lib/pkgdb.sh
3372+. "$TESTSLIB/pkgdb.sh"
3373+
3374+# shellcheck source=tests/lib/random.sh
3375+. "$TESTSLIB/random.sh"
3376+
3377+# shellcheck source=tests/lib/spread-funcs.sh
3378+. "$TESTSLIB/spread-funcs.sh"
3379+
3380+# shellcheck source=tests/lib/journalctl.sh
3381+. "$TESTSLIB/journalctl.sh"
3382+
3383+# shellcheck source=tests/lib/state.sh
3384+. "$TESTSLIB/state.sh"
3385+
3386+# shellcheck source=tests/lib/systems.sh
3387+. "$TESTSLIB/systems.sh"
3388+
3389+
3390+###
3391+### Utility functions reused below.
3392+###
3393+
3394+create_test_user(){
3395+ if ! id test >& /dev/null; then
3396+ quiet groupadd --gid 12345 test
3397+ case "$SPREAD_SYSTEM" in
3398+ ubuntu-*)
3399+ # manually setting the UID and GID to 12345 because we need to
3400+ # know the numbers match for when we set up the user inside
3401+ # the all-snap, which has its own user & group database.
3402+ # Nothing special about 12345 beyond it being high enough it's
3403+ # unlikely to ever clash with anything, and easy to remember.
3404+ quiet adduser --uid 12345 --gid 12345 --disabled-password --gecos '' test
3405+ ;;
3406+ debian-*|fedora-*|opensuse-*|arch-*|amazon-*)
3407+ quiet useradd -m --uid 12345 --gid 12345 test
3408+ ;;
3409+ *)
3410+ echo "ERROR: system $SPREAD_SYSTEM not yet supported!"
3411+ exit 1
3412+ esac
3413+ fi
3414+
3415+ owner=$( stat -c "%U:%G" /home/test )
3416+ if [ "$owner" != "test:test" ]; then
3417+ echo "expected /home/test to be test:test but it's $owner"
3418+ exit 1
3419+ fi
3420+ unset owner
3421+
3422+ echo 'test ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
3423+
3424+ chown test.test -R "$SPREAD_PATH"
3425+ chown test.test "$SPREAD_PATH/../"
3426+}
3427+
3428+build_deb(){
3429+ # Use fake version to ensure we are always bigger than anything else
3430+ dch --newversion "1337.$(dpkg-parsechangelog --show-field Version)" "testing build"
3431+
3432+ su -l -c "cd $PWD && DEB_BUILD_OPTIONS='nocheck testkeys' dpkg-buildpackage -tc -b -Zgzip" test
3433+ # put our debs to a safe place
3434+ cp ../*.deb "$GOHOME"
3435+}
3436+
3437+build_rpm() {
3438+ distro=$(echo "$SPREAD_SYSTEM" | awk '{split($0,a,"-");print a[1]}')
3439+ release=$(echo "$SPREAD_SYSTEM" | awk '{split($0,a,"-");print a[2]}')
3440+ if [[ "$SPREAD_SYSTEM" == amazon-linux-2-* ]]; then
3441+ distro=amzn
3442+ release=2
3443+ fi
3444+ arch=x86_64
3445+ base_version="$(head -1 debian/changelog | awk -F '[()]' '{print $2}')"
3446+ version="1337.$base_version"
3447+ packaging_path=packaging/$distro-$release
3448+ archive_name=snapd-$version.tar.gz
3449+ archive_compression=z
3450+ extra_tar_args=
3451+ rpm_dir=$(rpm --eval "%_topdir")
3452+
3453+ case "$SPREAD_SYSTEM" in
3454+ fedora-*|amazon-*)
3455+ extra_tar_args="$extra_tar_args --exclude=vendor/*"
3456+ ;;
3457+ opensuse-*)
3458+ archive_name=snapd_$version.vendor.tar.xz
3459+ archive_compression=J
3460+ ;;
3461+ *)
3462+ echo "ERROR: RPM build for system $SPREAD_SYSTEM is not yet supported"
3463+ exit 1
3464+ esac
3465+
3466+ sed -i -e "s/^Version:.*$/Version: $version/g" "$packaging_path/snapd.spec"
3467+
3468+ # Create a source tarball for the current snapd sources
3469+ mkdir -p "/tmp/pkg/snapd-$version"
3470+ cp -ra -- * "/tmp/pkg/snapd-$version/"
3471+ mkdir -p "$rpm_dir/SOURCES"
3472+ # shellcheck disable=SC2086
3473+ (cd /tmp/pkg && tar "-c${archive_compression}f" "$rpm_dir/SOURCES/$archive_name" $extra_tar_args "snapd-$version")
3474+ if [[ "$SPREAD_SYSTEM" == amazon-linux-2-* ]]; then
3475+ # need to build the vendor tree
3476+ (cd /tmp/pkg && tar "-cJf" "$rpm_dir/SOURCES/snapd_${version}.only-vendor.tar.xz" "snapd-$version/vendor")
3477+ fi
3478+ cp "$packaging_path"/* "$rpm_dir/SOURCES/"
3479+
3480+ # Cleanup all artifacts from previous builds
3481+ rm -rf "$rpm_dir"/BUILD/*
3482+
3483+ # Build our source package
3484+ rpmbuild --with testkeys -bs "$packaging_path/snapd.spec"
3485+
3486+ # .. and we need all necessary build dependencies available
3487+ deps=()
3488+ IFS=$'\n'
3489+ for dep in $(rpm -qpR "$rpm_dir"/SRPMS/snapd-1337.*.src.rpm); do
3490+ if [[ "$dep" = rpmlib* ]]; then
3491+ continue
3492+ fi
3493+ deps+=("$dep")
3494+ done
3495+ distro_install_package "${deps[@]}"
3496+
3497+ # And now build our binary package
3498+ rpmbuild \
3499+ --with testkeys \
3500+ --nocheck \
3501+ -ba \
3502+ "$packaging_path/snapd.spec"
3503+
3504+ cp "$rpm_dir"/RPMS/$arch/snap*.rpm "$GOPATH"
3505+ if [[ "$SPREAD_SYSTEM" = fedora-* ]]; then
3506+ # On Fedora we have an additional package for SELinux
3507+ cp "$rpm_dir"/RPMS/noarch/snap*.rpm "$GOPATH"
3508+ fi
3509+}
3510+
3511+build_arch_pkg() {
3512+ base_version="$(head -1 debian/changelog | awk -F '[()]' '{print $2}')"
3513+ version="1337.$base_version"
3514+ packaging_path=packaging/arch
3515+ archive_name=snapd-$version.tar
3516+
3517+ rm -rf /tmp/pkg
3518+ mkdir -p /tmp/pkg/sources/snapd
3519+ cp -ra -- * /tmp/pkg/sources/snapd/
3520+
3521+ # shellcheck disable=SC2086
3522+ tar -C /tmp/pkg/sources -cf "/tmp/pkg/$archive_name" "snapd"
3523+ cp "$packaging_path"/* "/tmp/pkg"
3524+
3525+ # fixup PKGBUILD which builds a package named snapd-git with dynamic version
3526+ # - update pkgname to use snapd
3527+ # - kill dynamic version
3528+ # - packaging functions are named package_<pkgname>(), update it to package_snapd()
3529+ # - update source path to point to local archive instead of git
3530+ # - fix package version to $version
3531+ sed -i \
3532+ -e "s/^source=.*/source=(\"$archive_name\")/" \
3533+ -e "s/pkgname=snapd.*/pkgname=snapd/" \
3534+ -e "s/pkgver=.*/pkgver=$version/" \
3535+ -e "s/package_snapd-git()/package_snapd()/" \
3536+ /tmp/pkg/PKGBUILD
3537+ # comment out automatic package version update block `pkgver() { ... }` as
3538+ # it's only useful when building the package manually
3539+ awk '
3540+ /BEGIN/ { strip = 0; last = 0 }
3541+ /pkgver\(\)/ { strip = 1 }
3542+ /^}/ { if (strip) last = 1 }
3543+ // { if (strip) { print "#" $0; if (last) { last = 0; strip = 0}} else { print $0}}
3544+ ' < /tmp/pkg/PKGBUILD > /tmp/pkg/PKGBUILD.tmp
3545+ mv /tmp/pkg/PKGBUILD.tmp /tmp/pkg/PKGBUILD
3546+
3547+ chown -R test:test /tmp/pkg
3548+ su -l -c "cd /tmp/pkg && WITH_TEST_KEYS=1 makepkg -f --nocheck" test
3549+
3550+ cp /tmp/pkg/snapd*.pkg.tar.xz "$GOPATH"
3551+}
3552+
3553+download_from_published(){
3554+ local published_version="$1"
3555+
3556+ curl -s -o pkg_page "https://launchpad.net/ubuntu/+source/snapd/$published_version"
3557+
3558+ arch=$(dpkg --print-architecture)
3559+ build_id=$(sed -n 's|<a href="/ubuntu/+source/snapd/'"$published_version"'/+build/\(.*\)">'"$arch"'</a>|\1|p' pkg_page | sed -e 's/^[[:space:]]*//')
3560+
3561+ # we need to download snap-confine and ubuntu-core-launcher for versions < 2.23
3562+ for pkg in snapd snap-confine ubuntu-core-launcher; do
3563+ file="${pkg}_${published_version}_${arch}.deb"
3564+ curl -L -o "$GOHOME/$file" "https://launchpad.net/ubuntu/+source/snapd/${published_version}/+build/${build_id}/+files/${file}"
3565+ done
3566+}
3567+
3568+install_dependencies_from_published(){
3569+ local published_version="$1"
3570+
3571+ for dep in snap-confine ubuntu-core-launcher; do
3572+ dpkg -i "$GOHOME/${dep}_${published_version}_$(dpkg --print-architecture).deb"
3573+ done
3574+}
3575+
3576+###
3577+### Prepare / restore functions for {project,suite}
3578+###
3579+
3580+prepare_project() {
3581+ # Check if running inside a container.
3582+ # The testsuite will not work in such an environment
3583+ if systemd-detect-virt -c; then
3584+ echo "Tests cannot run inside a container"
3585+ exit 1
3586+ fi
3587+
3588+ # Set REUSE_PROJECT to reuse the previous prepare when also reusing the server.
3589+ [ "$REUSE_PROJECT" != 1 ] || exit 0
3590+ echo "Running with SNAP_REEXEC: $SNAP_REEXEC"
3591+
3592+ # check that we are not updating
3593+ if [ "$(bootenv snap_mode)" = "try" ]; then
3594+ echo "Ongoing reboot upgrade process, please try again when finished"
3595+ exit 1
3596+ fi
3597+
3598+ # Prepare the state directories for execution
3599+ prepare_state
3600+
3601+ # declare the "quiet" wrapper
3602+
3603+ if [ "$SPREAD_BACKEND" = external ]; then
3604+ chown test.test -R "$PROJECT_PATH"
3605+ exit 0
3606+ fi
3607+
3608+ if [ "$SPREAD_BACKEND" = qemu ]; then
3609+ if [ -d /etc/apt/apt.conf.d ]; then
3610+ # qemu images may be built with pre-baked proxy settings that can be wrong
3611+ rm -f /etc/apt/apt.conf.d/90cloud-init-aptproxy
3612+ rm -f /etc/apt/apt.conf.d/99proxy
3613+ if [ -n "${HTTP_PROXY:-}" ]; then
3614+ printf 'Acquire::http::Proxy "%s";\n' "$HTTP_PROXY" >> /etc/apt/apt.conf.d/99proxy
3615+ fi
3616+ if [ -n "${HTTPS_PROXY:-}" ]; then
3617+ printf 'Acquire::https::Proxy "%s";\n' "$HTTPS_PROXY" >> /etc/apt/apt.conf.d/99proxy
3618+ fi
3619+ fi
3620+ if [ -f /etc/dnf/dnf.conf ]; then
3621+ if [ -n "${HTTP_PROXY:-}" ]; then
3622+ echo "proxy=$HTTP_PROXY" >> /etc/dnf/dnf.conf
3623+ fi
3624+ fi
3625+ # TODO: zypper proxy, yum proxy
3626+ fi
3627+
3628+ create_test_user
3629+
3630+ distro_update_package_db
3631+
3632+ if [[ "$SPREAD_SYSTEM" == arch-* ]]; then
3633+ # perform system upgrade on Arch so that we run with most recent kernel
3634+ # and userspace
3635+ if [[ "$SPREAD_REBOOT" == 0 ]]; then
3636+ if distro_upgrade | MATCH "reboot"; then
3637+ echo "system upgraded, reboot required"
3638+ REBOOT
3639+ fi
3640+ # arch uses a single kernel package which could have gotten updated
3641+ # just now, reboot in case we're still on the old kernel
3642+ if [ ! -d "/lib/modules/$(uname -r)" ]; then
3643+ echo "rebooting to new kernel"
3644+ REBOOT
3645+ fi
3646+ fi
3647+ # double check we are running the installed kernel
3648+ # NOTE: LOCALVERSION is set by scripts/setlocalversion and loos like
3649+ # 4.17.11-arch1, since this may not match pacman -Qi output, we'll list
3650+ # the files within the package instead
3651+ # pacman -Ql linux output:
3652+ # ...
3653+ # linux /usr/lib/modules/4.17.11-arch1/modules.alias
3654+ if [[ "$(pacman -Ql linux | cut -f2 -d' ' |grep '/usr/lib/modules/.*/modules'|cut -f5 -d/ | uniq)" != "$(uname -r)" ]]; then
3655+ echo "running unexpected kernel version $(uname -r)"
3656+ exit 1
3657+ fi
3658+ fi
3659+
3660+ if [[ "$SPREAD_SYSTEM" == ubuntu-14.04-* ]]; then
3661+ if [ ! -d packaging/ubuntu-14.04 ]; then
3662+ echo "no packaging/ubuntu-14.04/ directory "
3663+ echo "broken test setup"
3664+ exit 1
3665+ fi
3666+
3667+ # 14.04 has its own packaging
3668+ ./generate-packaging-dir
3669+
3670+ quiet apt-get install -y software-properties-common
3671+
3672+ echo 'deb http://archive.ubuntu.com/ubuntu/ trusty-proposed main universe' >> /etc/apt/sources.list
3673+ quiet add-apt-repository ppa:snappy-dev/image
3674+ quiet apt-get update
3675+
3676+ quiet apt-get install -y --install-recommends linux-generic-lts-xenial
3677+ quiet apt-get install -y --force-yes apparmor libapparmor1 seccomp libseccomp2 systemd cgroup-lite util-linux
3678+ fi
3679+
3680+ distro_purge_package snapd || true
3681+ install_pkg_dependencies
3682+
3683+ # We take a special case for Debian/Ubuntu where we install additional build deps
3684+ # base on the packaging. In Fedora/Suse this is handled via mock/osc
3685+ case "$SPREAD_SYSTEM" in
3686+ debian-*|ubuntu-*)
3687+ # in 16.04: apt build-dep -y ./
3688+ gdebi --quiet --apt-line ./debian/control | quiet xargs -r apt-get install -y
3689+ ;;
3690+ esac
3691+
3692+ # update vendoring
3693+ if [ -z "$(command -v govendor)" ]; then
3694+ rm -rf "$GOPATH/src/github.com/kardianos/govendor"
3695+ go get -u github.com/kardianos/govendor
3696+ fi
3697+ quiet govendor sync
3698+ # govendor runs as root and will leave strange permissions
3699+ chown test.test -R "$SPREAD_PATH"
3700+
3701+ if [ -z "$SNAPD_PUBLISHED_VERSION" ]; then
3702+ case "$SPREAD_SYSTEM" in
3703+ ubuntu-*|debian-*)
3704+ build_deb
3705+ ;;
3706+ fedora-*|opensuse-*|amazon-*)
3707+ build_rpm
3708+ ;;
3709+ arch-*)
3710+ build_arch_pkg
3711+ ;;
3712+ *)
3713+ echo "ERROR: No build instructions available for system $SPREAD_SYSTEM"
3714+ exit 1
3715+ ;;
3716+ esac
3717+ else
3718+ download_from_published "$SNAPD_PUBLISHED_VERSION"
3719+ install_dependencies_from_published "$SNAPD_PUBLISHED_VERSION"
3720+ fi
3721+
3722+ # Build fakestore.
3723+ fakestore_tags=
3724+ if [ "$REMOTE_STORE" = staging ]; then
3725+ fakestore_tags="-tags withstagingkeys"
3726+ fi
3727+
3728+ # eval to prevent expansion errors on opensuse (the variable keeps quotes)
3729+ eval "go get $fakestore_tags ./tests/lib/fakestore/cmd/fakestore"
3730+
3731+ # Build additional utilities we need for testing
3732+ go get ./tests/lib/fakedevicesvc
3733+ go get ./tests/lib/systemd-escape
3734+
3735+ # Disable journald rate limiting
3736+ mkdir -p /etc/systemd/journald.conf.d
3737+ # The RateLimitIntervalSec key is not supported on some systemd versions causing
3738+ # the journal rate limit could be considered as not valid and discarded in concecuence.
3739+ # RateLimitInterval key is supported in old systemd versions and in new ones as well,
3740+ # maintaining backward compatibility.
3741+ cat <<-EOF > /etc/systemd/journald.conf.d/no-rate-limit.conf
3742+ [Journal]
3743+ RateLimitInterval=0
3744+ RateLimitBurst=0
3745+EOF
3746+ systemctl restart systemd-journald.service
3747+}
3748+
3749+prepare_project_each() {
3750+ # Clear the kernel ring buffer.
3751+ dmesg -c > /dev/null
3752+
3753+ fixup_dev_random
3754+}
3755+
3756+prepare_suite() {
3757+ # shellcheck source=tests/lib/prepare.sh
3758+ . "$TESTSLIB"/prepare.sh
3759+ if is_core_system; then
3760+ prepare_ubuntu_core
3761+ else
3762+ prepare_classic
3763+ fi
3764+}
3765+
3766+prepare_suite_each() {
3767+ # save the job which is going to be exeuted in the system
3768+ echo -n "$SPREAD_JOB " >> "$RUNTIME_STATE_PATH/runs"
3769+ # shellcheck source=tests/lib/reset.sh
3770+ "$TESTSLIB"/reset.sh --reuse-core
3771+ # Reset systemd journal cursor.
3772+ start_new_journalctl_log
3773+ # shellcheck source=tests/lib/prepare.sh
3774+ . "$TESTSLIB"/prepare.sh
3775+ if is_classic_system; then
3776+ prepare_each_classic
3777+ fi
3778+ # Check if journalctl is ready to run the test
3779+ check_journalctl_ready
3780+}
3781+
3782+restore_suite_each() {
3783+ true
3784+}
3785+
3786+restore_suite() {
3787+ # shellcheck source=tests/lib/reset.sh
3788+ "$TESTSLIB"/reset.sh --store
3789+ if is_classic_system; then
3790+ # shellcheck source=tests/lib/pkgdb.sh
3791+ . "$TESTSLIB"/pkgdb.sh
3792+ distro_purge_package snapd
3793+ if [[ "$SPREAD_SYSTEM" != opensuse-* && "$SPREAD_SYSTEM" != arch-* ]]; then
3794+ # A snap-confine package never existed on openSUSE or Arch
3795+ distro_purge_package snap-confine
3796+ fi
3797+ fi
3798+}
3799+
3800+restore_project_each() {
3801+ restore_dev_random
3802+
3803+ # Udev rules are notoriously hard to write and seemingly correct but subtly
3804+ # wrong rules can pass review. Whenever that happens udev logs an error
3805+ # message. As a last resort from lack of a better mechanism we can try to
3806+ # pick up such errors.
3807+ if grep "invalid .*snap.*.rules" /var/log/syslog; then
3808+ echo "Invalid udev file detected, test most likely broke it"
3809+ exit 1
3810+ fi
3811+
3812+ # Check if the OOM killer got invoked - if that is the case our tests
3813+ # will most likely not function correctly anymore. It looks like this
3814+ # happens with: https://forum.snapcraft.io/t/4101 and is a source of
3815+ # failure in the autopkgtest environment.
3816+ if dmesg|grep "oom-killer"; then
3817+ echo "oom-killer got invoked during the tests, this should not happen."
3818+ echo "Dmesg debug output:"
3819+ dmesg
3820+ echo "Meminfo debug output:"
3821+ cat /proc/meminfo
3822+ exit 1
3823+ fi
3824+
3825+ # check if there is a shutdown pending, no test should trigger this
3826+ # and it leads to very confusing test failures
3827+ if [ -e /run/systemd/shutdown/scheduled ]; then
3828+ echo "Test triggered a shutdown, this should not happen"
3829+ snap changes
3830+ exit 1
3831+ fi
3832+
3833+ # Check for kernel oops during the tests
3834+ if dmesg|grep "Oops: "; then
3835+ echo "A kernel oops happened during the tests, test results will be unreliable"
3836+ echo "Dmesg debug output:"
3837+ dmesg
3838+ exit 1
3839+ fi
3840+}
3841+
3842+restore_project() {
3843+ # Delete the snapd state used to accelerate prepare/restore code in certain suites.
3844+ delete_snapd_state
3845+
3846+ # Remove all of the code we pushed and any build results. This removes
3847+ # stale files and we cannot do incremental builds anyway so there's little
3848+ # point in keeping them.
3849+ if [ -n "$GOPATH" ]; then
3850+ rm -rf "${GOPATH%%:*}"
3851+ fi
3852+
3853+ rm -rf /etc/systemd/journald.conf.d/no-rate-limit.conf
3854+ rmdir /etc/systemd/journald.conf.d || true
3855+}
3856+
3857+case "$1" in
3858+ --prepare-project)
3859+ prepare_project
3860+ ;;
3861+ --prepare-project-each)
3862+ prepare_project_each
3863+ ;;
3864+ --prepare-suite)
3865+ prepare_suite
3866+ ;;
3867+ --prepare-suite-each)
3868+ prepare_suite_each
3869+ ;;
3870+ --restore-suite-each)
3871+ restore_suite_each
3872+ ;;
3873+ --restore-suite)
3874+ restore_suite
3875+ ;;
3876+ --restore-project-each)
3877+ restore_project_each
3878+ ;;
3879+ --restore-project)
3880+ restore_project
3881+ ;;
3882+ *)
3883+ echo "unsupported argument: $1"
3884+ echo "try one of --{prepare,restore}-{project,suite}{,-each}"
3885+ exit 1
3886+ ;;
3887+esac
3888diff --git a/tests/lib/prepare.sh b/tests/lib/prepare.sh
3889new file mode 100755
3890index 0000000..fa5f019
3891--- /dev/null
3892+++ b/tests/lib/prepare.sh
3893@@ -0,0 +1,634 @@
3894+#!/bin/bash
3895+
3896+set -eux
3897+
3898+# shellcheck source=tests/lib/dirs.sh
3899+. "$TESTSLIB/dirs.sh"
3900+# shellcheck source=tests/lib/snaps.sh
3901+. "$TESTSLIB/snaps.sh"
3902+# shellcheck source=tests/lib/pkgdb.sh
3903+. "$TESTSLIB/pkgdb.sh"
3904+# shellcheck source=tests/lib/boot.sh
3905+. "$TESTSLIB/boot.sh"
3906+# shellcheck source=tests/lib/spread-funcs.sh
3907+. "$TESTSLIB/spread-funcs.sh"
3908+# shellcheck source=tests/lib/state.sh
3909+. "$TESTSLIB/state.sh"
3910+# shellcheck source=tests/lib/systems.sh
3911+. "$TESTSLIB/systems.sh"
3912+
3913+
3914+disable_kernel_rate_limiting() {
3915+ # kernel rate limiting hinders debugging security policy so turn it off
3916+ echo "Turning off kernel rate-limiting"
3917+ # TODO: we should be able to run the tests with rate limiting disabled so
3918+ # debug output is robust, but we currently can't :(
3919+ echo "SKIPPED: see https://forum.snapcraft.io/t/snapd-spread-tests-should-be-able-to-run-with-kernel-rate-limiting-disabled/424"
3920+ #sysctl -w kernel.printk_ratelimit=0
3921+}
3922+
3923+ensure_jq() {
3924+ if command -v jq; then
3925+ return
3926+ fi
3927+
3928+ if is_core18_system; then
3929+ snap install --devmode jq-core18
3930+ snap alias jq-core18.jq jq
3931+ else
3932+ snap install --devmode jq
3933+ fi
3934+}
3935+
3936+disable_refreshes() {
3937+ echo "Ensure jq is available"
3938+ ensure_jq
3939+
3940+ echo "Modify state to make it look like the last refresh just happened"
3941+ systemctl stop snapd.socket snapd.service
3942+ jq ".data[\"last-refresh\"] = \"$(date +%Y-%m-%dT%H:%M:%S%:z)\"" /var/lib/snapd/state.json > /var/lib/snapd/state.json.new
3943+ mv /var/lib/snapd/state.json.new /var/lib/snapd/state.json
3944+ systemctl start snapd.socket snapd.service
3945+
3946+ echo "Minimize risk of hitting refresh schedule"
3947+ snap set core refresh.schedule=00:00-23:59
3948+ snap refresh --time --abs-time | MATCH "last: 2[0-9]{3}"
3949+
3950+ echo "Ensure jq is gone"
3951+ snap remove jq jq-core18
3952+}
3953+
3954+setup_systemd_snapd_overrides() {
3955+ START_LIMIT_INTERVAL="StartLimitInterval=0"
3956+ if [[ "$SPREAD_SYSTEM" =~ opensuse-42.[23]-* ]]; then
3957+ # StartLimitInterval is not supported by the systemd version
3958+ # openSUSE 42.2/3 ship.
3959+ START_LIMIT_INTERVAL=""
3960+ fi
3961+
3962+ mkdir -p /etc/systemd/system/snapd.service.d
3963+ cat <<EOF > /etc/systemd/system/snapd.service.d/local.conf
3964+[Unit]
3965+$START_LIMIT_INTERVAL
3966+[Service]
3967+Environment=SNAPD_DEBUG_HTTP=7 SNAPD_DEBUG=1 SNAPPY_TESTING=1 SNAPD_REBOOT_DELAY=10m SNAPD_CONFIGURE_HOOK_TIMEOUT=30s SNAPPY_USE_STAGING_STORE=$SNAPPY_USE_STAGING_STORE
3968+ExecStartPre=/bin/touch /dev/iio:device0
3969+EOF
3970+ mkdir -p /etc/systemd/system/snapd.socket.d
3971+ cat <<EOF > /etc/systemd/system/snapd.socket.d/local.conf
3972+[Unit]
3973+$START_LIMIT_INTERVAL
3974+EOF
3975+
3976+ # We change the service configuration so reload and restart
3977+ # the snapd socket unit to get them applied
3978+ systemctl daemon-reload
3979+ systemctl restart snapd.socket
3980+}
3981+
3982+update_core_snap_for_classic_reexec() {
3983+ # it is possible to disable this to test that snapd (the deb) works
3984+ # fine with whatever is in the core snap
3985+ if [ "$MODIFY_CORE_SNAP_FOR_REEXEC" != "1" ]; then
3986+ echo "Not modifying the core snap as requested via MODIFY_CORE_SNAP_FOR_REEXEC"
3987+ return
3988+ fi
3989+
3990+ # We want to use the in-tree snap/snapd/snap-exec/snapctl, because
3991+ # we re-exec by default.
3992+ # To accomplish that, we'll just unpack the core we just grabbed,
3993+ # shove the new snap-exec and snapctl in there, and repack it.
3994+
3995+ # First of all, unmount the core
3996+ core="$(readlink -f "$SNAP_MOUNT_DIR/core/current" || readlink -f "$SNAP_MOUNT_DIR/ubuntu-core/current")"
3997+ snap="$(mount | grep " $core" | awk '{print $1}')"
3998+ umount --verbose "$core"
3999+
4000+ # Now unpack the core, inject the new snap-exec/snapctl into it
4001+ unsquashfs -no-progress "$snap"
4002+ # clean the old snapd binaries, just in case
4003+ rm squashfs-root/usr/lib/snapd/* squashfs-root/usr/bin/{snap,snapctl}
4004+ # and copy in the current libexec
4005+ cp -a "$LIBEXECDIR"/snapd/* squashfs-root/usr/lib/snapd/
4006+ # also the binaries themselves
4007+ cp -a /usr/bin/{snap,snapctl} squashfs-root/usr/bin/
4008+ # make sure bin/snapctl is a symlink to lib/
4009+ if [ ! -L squashfs-root/usr/bin/snapctl ]; then
4010+ mv squashfs-root/usr/bin/snapctl squashfs-root/usr/lib/snapd
4011+ ln -s ../lib/snapd/snapctl squashfs-root/usr/bin/snapctl
4012+ fi
4013+
4014+ case "$SPREAD_SYSTEM" in
4015+ ubuntu-*|debian-*)
4016+ # and snap-confine's apparmor
4017+ if [ -e /etc/apparmor.d/usr.lib.snapd.snap-confine.real ]; then
4018+ cp -a /etc/apparmor.d/usr.lib.snapd.snap-confine.real squashfs-root/etc/apparmor.d/usr.lib.snapd.snap-confine.real
4019+ else
4020+ cp -a /etc/apparmor.d/usr.lib.snapd.snap-confine squashfs-root/etc/apparmor.d/usr.lib.snapd.snap-confine.real
4021+ fi
4022+ ;;
4023+ esac
4024+
4025+ case "$SPREAD_SYSTEM" in
4026+ ubuntu-*)
4027+ # also load snap-confine's apparmor profile
4028+ apparmor_parser -r squashfs-root/etc/apparmor.d/usr.lib.snapd.snap-confine.real
4029+ ;;
4030+ esac
4031+
4032+ # repack, cheating to speed things up (4sec vs 1.5min)
4033+ mv "$snap" "${snap}.orig"
4034+ mksnap_fast "squashfs-root" "$snap"
4035+ chmod --reference="${snap}.orig" "$snap"
4036+ rm -rf squashfs-root
4037+
4038+ # Now mount the new core snap, first discarding the old mount namespace
4039+ "$LIBEXECDIR/snapd/snap-discard-ns" core
4040+ mount "$snap" "$core"
4041+
4042+ check_file() {
4043+ if ! cmp "$1" "$2" ; then
4044+ echo "$1 in tree and $2 in core snap are unexpectedly not the same"
4045+ exit 1
4046+ fi
4047+ }
4048+
4049+ # Make sure we're running with the correct copied bits
4050+ for p in "$LIBEXECDIR/snapd/snap-exec" "$LIBEXECDIR/snapd/snap-confine" "$LIBEXECDIR/snapd/snap-discard-ns" "$LIBEXECDIR/snapd/snapd" "$LIBEXECDIR/snapd/snap-update-ns"; do
4051+ check_file "$p" "$core/usr/lib/snapd/$(basename "$p")"
4052+ done
4053+ for p in /usr/bin/snapctl /usr/bin/snap; do
4054+ check_file "$p" "$core$p"
4055+ done
4056+}
4057+
4058+prepare_each_classic() {
4059+ mkdir -p /etc/systemd/system/snapd.service.d
4060+ if [ -z "${SNAP_REEXEC:-}" ]; then
4061+ rm -f /etc/systemd/system/snapd.service.d/reexec.conf
4062+ else
4063+ cat <<EOF > /etc/systemd/system/snapd.service.d/reexec.conf
4064+[Service]
4065+Environment=SNAP_REEXEC=$SNAP_REEXEC
4066+EOF
4067+ fi
4068+ # the re-exec setting may have changed in the service so we need
4069+ # to ensure snapd is reloaded
4070+ systemctl daemon-reload
4071+ systemctl restart snapd
4072+
4073+ if [ ! -f /etc/systemd/system/snapd.service.d/local.conf ]; then
4074+ echo "/etc/systemd/system/snapd.service.d/local.conf vanished!"
4075+ exit 1
4076+ fi
4077+}
4078+
4079+prepare_classic() {
4080+ distro_install_build_snapd
4081+ if snap --version |MATCH unknown; then
4082+ echo "Package build incorrect, 'snap --version' mentions 'unknown'"
4083+ snap --version
4084+ distro_query_package_info snapd
4085+ exit 1
4086+ fi
4087+ if "$LIBEXECDIR/snapd/snap-confine" --version | MATCH unknown; then
4088+ echo "Package build incorrect, 'snap-confine --version' mentions 'unknown'"
4089+ "$LIBEXECDIR/snapd/snap-confine" --version
4090+ case "$SPREAD_SYSTEM" in
4091+ ubuntu-*|debian-*)
4092+ apt-cache policy snapd
4093+ ;;
4094+ fedora-*)
4095+ dnf info snapd
4096+ ;;
4097+ esac
4098+ exit 1
4099+ fi
4100+
4101+ # Some systems (google:ubuntu-16.04-64) ship with a broken sshguard
4102+ # unit. Stop the broken unit to not confuse the "degraded-boot" test.
4103+ #
4104+ # FIXME: fix the ubuntu-16.04-64 image
4105+ if systemctl list-unit-files | grep sshguard.service; then
4106+ if ! systemctl status sshguard.service; then
4107+ systemctl stop sshguard.service
4108+ systemctl reset-failed sshguard.service
4109+ fi
4110+ fi
4111+
4112+ setup_systemd_snapd_overrides
4113+
4114+ if [ "$REMOTE_STORE" = staging ]; then
4115+ # shellcheck source=tests/lib/store.sh
4116+ . "$TESTSLIB/store.sh"
4117+ # reset seeding data that is likely tainted with production keys
4118+ systemctl stop snapd.service snapd.socket
4119+ rm -rf /var/lib/snapd/assertions/*
4120+ rm -f /var/lib/snapd/state.json
4121+ setup_staging_store
4122+ fi
4123+
4124+ # Snapshot the state including core.
4125+ if ! is_snapd_state_saved; then
4126+ # Pre-cache a few heavy snaps so that they can be installed by tests
4127+ # quickly. This relies on a behavior of snapd where .partial files are
4128+ # used for resuming downloads.
4129+ (
4130+ set -x
4131+ cd "$TESTSLIB/cache/"
4132+ # Download each of the snaps we want to pre-cache. Note that `snap download`
4133+ # a quick no-op if the file is complete.
4134+ for snap_name in ${PRE_CACHE_SNAPS:-}; do
4135+ snap download "$snap_name"
4136+ done
4137+ # Copy all of the snaps back to the spool directory. From there we
4138+ # will reuse them during subsequent `snap install` operations.
4139+ cp -- *.snap /var/lib/snapd/snaps/
4140+ set +x
4141+ )
4142+
4143+ ! snap list | grep core || exit 1
4144+ # use parameterized core channel (defaults to edge) instead
4145+ # of a fixed one and close to stable in order to detect defects
4146+ # earlier
4147+ snap install --"$CORE_CHANNEL" core
4148+ snap list | grep core
4149+
4150+ systemctl stop snapd.{service,socket}
4151+ update_core_snap_for_classic_reexec
4152+ systemctl start snapd.{service,socket}
4153+
4154+ disable_refreshes
4155+
4156+ echo "Ensure that the bootloader environment output does not contain any of the snap_* variables on classic"
4157+ # shellcheck disable=SC2119
4158+ output=$(bootenv)
4159+ if echo "$output" | MATCH snap_ ; then
4160+ echo "Expected bootloader environment without snap_*, got:"
4161+ echo "$output"
4162+ exit 1
4163+ fi
4164+
4165+ systemctl stop snapd.{service,socket}
4166+ save_snapd_state
4167+ systemctl start snapd.socket
4168+ fi
4169+
4170+ disable_kernel_rate_limiting
4171+
4172+ if [[ "$SPREAD_SYSTEM" == arch-* ]]; then
4173+ # Arch packages do not ship empty directories by default, hence there is
4174+ # no /etc/dbus-1/system.d what prevents dbus from properly establishing
4175+ # inotify watch on that path
4176+ mkdir -p /etc/dbus-1/system.d
4177+ systemctl reload dbus.service
4178+ fi
4179+}
4180+
4181+setup_reflash_magic() {
4182+ # install the stuff we need
4183+ distro_install_package kpartx busybox-static
4184+ distro_install_local_package "$GOHOME"/snapd_*.deb
4185+ distro_clean_package_cache
4186+
4187+ # we cannot use "names.sh" here because no snaps are installed yet
4188+ core_name="core"
4189+ if is_core18_system; then
4190+ snap download "--channel=${SNAPD_CHANNEL}" snapd
4191+ core_name="core18"
4192+ fi
4193+ snap install "--channel=${CORE_CHANNEL}" "$core_name"
4194+
4195+ # install ubuntu-image
4196+ snap install --classic --edge ubuntu-image
4197+
4198+ # needs to be under /home because ubuntu-device-flash
4199+ # uses snap-confine and that will hide parts of the hostfs
4200+ IMAGE_HOME=/home/image
4201+ mkdir -p "$IMAGE_HOME"
4202+
4203+ # ensure that ubuntu-image is using our test-build of snapd with the
4204+ # test keys and not the bundled version of usr/bin/snap from the snap.
4205+ # Note that we can not put it into /usr/bin as '/usr' is different
4206+ # when the snap uses confinement.
4207+ cp /usr/bin/snap "$IMAGE_HOME"
4208+ export UBUNTU_IMAGE_SNAP_CMD="$IMAGE_HOME/snap"
4209+
4210+ if is_core18_system; then
4211+ # modify the snapd snap so that it has our snapd
4212+ UNPACK_DIR="/tmp/snapd-snap"
4213+ unsquashfs -no-progress -d "$UNPACK_DIR" snapd_*.snap
4214+ dpkg-deb -x "$SPREAD_PATH"/../snapd_*.deb "$UNPACK_DIR"
4215+ snap pack "$UNPACK_DIR" "$IMAGE_HOME"
4216+
4217+ # FIXME: fetch directly once its in the assertion service
4218+ cp "$TESTSLIB/assertions/ubuntu-core-18-amd64.model" "$IMAGE_HOME/pc.model"
4219+
4220+ IMAGE=core18-amd64.img
4221+
4222+ # TODO: once we have a real "canonical" signed core18 model
4223+ # use this and remove the extra assertions setup below.
4224+ #
4225+ # Note we don't need teardown, once the image is written
4226+ # the system reboots anyway.
4227+ #
4228+ # We can do this once https://forum.snapcraft.io/t/5947 is
4229+ # answered.
4230+ echo "Added needed assertions so that ubuntu-core-18-amd64.model works"
4231+ # shellcheck source=tests/lib/store.sh
4232+ . "$TESTSLIB/store.sh"
4233+ STORE_DIR="$(pwd)/fake-store-blobdir"
4234+ export STORE_DIR
4235+ STORE_ADDR="localhost:11028"
4236+ export STORE_ADDR
4237+ setup_fake_store "$STORE_DIR"
4238+ cp "$TESTSLIB"/assertions/developer1.account "$STORE_DIR"/asserts
4239+ cp "$TESTSLIB"/assertions/developer1.account-key "$STORE_DIR"/asserts
4240+ # have snap use the fakestore for assertions (but nothing else)
4241+ SNAPPY_FORCE_SAS_URL="http://$STORE_ADDR"
4242+ export SNAPPY_FORCE_SAS_URL
4243+ # -----------------------8<----------------------------
4244+ else
4245+ # modify the core snap so that the current root-pw works there
4246+ # for spread to do the first login
4247+ UNPACK_DIR="/tmp/core-snap"
4248+ unsquashfs -no-progress -d "$UNPACK_DIR" /var/lib/snapd/snaps/core_*.snap
4249+
4250+ # FIXME: install would be better but we don't have dpkg on
4251+ # the image
4252+ # unpack our freshly build snapd into the new snapd snap
4253+ dpkg-deb -x "$SPREAD_PATH"/../snapd_*.deb "$UNPACK_DIR"
4254+ # ensure any new timer units are available
4255+ cp -a /etc/systemd/system/timers.target.wants/*.timer "$UNPACK_DIR/etc/systemd/system/timers.target.wants"
4256+
4257+ # add gpio and iio slots
4258+ cat >> "$UNPACK_DIR/meta/snap.yaml" <<-EOF
4259+slots:
4260+ gpio-pin:
4261+ interface: gpio
4262+ number: 100
4263+ direction: out
4264+ iio0:
4265+ interface: iio
4266+ path: /dev/iio:device0
4267+EOF
4268+
4269+ # build new core snap for the image
4270+ snap pack "$UNPACK_DIR" "$IMAGE_HOME"
4271+
4272+ # FIXME: fetch directly once its in the assertion service
4273+ cp "$TESTSLIB/assertions/pc-${REMOTE_STORE}.model" "$IMAGE_HOME/pc.model"
4274+
4275+ # FIXME: how to test store updated of ubuntu-core with sideloaded snap?
4276+ IMAGE=all-snap-amd64.img
4277+ fi
4278+
4279+ EXTRA_FUNDAMENTAL=
4280+ IMAGE_CHANNEL=edge
4281+ if [ "$KERNEL_CHANNEL" = "$GADGET_CHANNEL" ]; then
4282+ IMAGE_CHANNEL="$KERNEL_CHANNEL"
4283+ else
4284+ # download pc-kernel snap for the specified channel and set
4285+ # ubuntu-image channel to that of the gadget, so that we don't
4286+ # need to download it
4287+ snap download --channel="$KERNEL_CHANNEL" pc-kernel
4288+
4289+ EXTRA_FUNDAMENTAL="--extra-snaps $PWD/pc-kernel_*.snap"
4290+ IMAGE_CHANNEL="$GADGET_CHANNEL"
4291+ fi
4292+
4293+ # 'snap pack' creates snaps 0644, and ubuntu-image just copies those in
4294+ # maybe we should fix one or both of those, but for now this'll do
4295+ chmod 0600 "$IMAGE_HOME"/*.snap
4296+
4297+ # on core18 we need to use the modified snapd snap and on core16
4298+ # it is the modified core that contains our freshly build snapd
4299+ if is_core18_system; then
4300+ extra_snap=("$IMAGE_HOME"/snapd_*.snap)
4301+ else
4302+ extra_snap=("$IMAGE_HOME"/core_*.snap)
4303+ fi
4304+
4305+ # extra_snap should contain only ONE snap
4306+ if "${#extra_snap[@]}" -ne 1; then
4307+ echo "unexpected number of globbed snaps: ${extra_snap[*]}"
4308+ exit 1
4309+ fi
4310+
4311+ /snap/bin/ubuntu-image -w "$IMAGE_HOME" "$IMAGE_HOME/pc.model" \
4312+ --channel "$IMAGE_CHANNEL" \
4313+ "$EXTRA_FUNDAMENTAL" \
4314+ --extra-snaps "${extra_snap[0]}" \
4315+ --output "$IMAGE_HOME/$IMAGE"
4316+ rm -f ./pc-kernel_*.{snap,assert} ./pc_*.{snap,assert}
4317+
4318+ # mount fresh image and add all our SPREAD_PROJECT data
4319+ kpartx -avs "$IMAGE_HOME/$IMAGE"
4320+ # FIXME: hardcoded mapper location, parse from kpartx
4321+ if is_core18_system; then
4322+ mount /dev/mapper/loop3p3 /mnt
4323+ else
4324+ mount /dev/mapper/loop2p3 /mnt
4325+ fi
4326+ mkdir -p /mnt/user-data/
4327+ # copy over everything from gopath to user-data, exclude:
4328+ # - VCS files
4329+ # - built debs
4330+ # - golang archive files and built packages dir
4331+ # - govendor .cache directory and the binary,
4332+ rsync -a -C \
4333+ --exclude '*.a' \
4334+ --exclude '*.deb' \
4335+ --exclude /gopath/.cache/ \
4336+ --exclude /gopath/bin/govendor \
4337+ --exclude /gopath/pkg/ \
4338+ /home/gopath /mnt/user-data/
4339+
4340+ # now modify the image
4341+ if is_core18_system; then
4342+ UNPACK_DIR="/tmp/core18-snap"
4343+ unsquashfs -no-progress -d "$UNPACK_DIR" /var/lib/snapd/snaps/core18_*.snap
4344+ fi
4345+
4346+ # create test user and ubuntu user inside the writable partition
4347+ # so that we can use a stock core in tests
4348+ mkdir -p /mnt/user-data/test
4349+
4350+ # create test user, see the comment in spread.yaml about 12345
4351+ mkdir -p /mnt/system-data/etc/sudoers.d/
4352+ echo 'test ALL=(ALL) NOPASSWD:ALL' >> /mnt/system-data/etc/sudoers.d/99-test-user
4353+ echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' >> /mnt/system-data/etc/sudoers.d/99-ubuntu-user
4354+ # modify sshd so that we can connect as root
4355+ mkdir -p /mnt/system-data/etc/ssh
4356+ cp -a "$UNPACK_DIR"/etc/ssh/* /mnt/system-data/etc/ssh/
4357+ # core18 is different here than core16
4358+ sed -i 's/\#\?\(PermitRootLogin\|PasswordAuthentication\)\>.*/\1 yes/' /mnt/system-data/etc/ssh/sshd_config
4359+ # ensure the setting is correct
4360+ grep '^PermitRootLogin yes' /mnt/system-data/etc/ssh/sshd_config
4361+
4362+ # build the user database - this is complicated because:
4363+ # - spread on linode wants to login as "root"
4364+ # - "root" login on the stock core snap is disabled
4365+ # - uids between classic/core differ
4366+ # - passwd,shadow on core are read-only
4367+ # - we cannot add root to extrausers as system passwd is searched first
4368+ # - we need to add our ubuntu and test users too
4369+ # So we create the user db we need in /root/test-etc/*:
4370+ # - take core passwd without "root"
4371+ # - append root
4372+ # - make sure the group matches
4373+ # - bind mount /root/test-etc/* to /etc/* via custom systemd job
4374+ # We also create /var/lib/extrausers/* and append ubuntu,test there
4375+ mkdir -p /mnt/system-data/root/test-etc
4376+ mkdir -p /mnt/system-data/var/lib/extrausers/
4377+ touch /mnt/system-data/var/lib/extrausers/sub{uid,gid}
4378+ mkdir -p /mnt/system-data/etc/systemd/system/multi-user.target.wants
4379+ for f in group gshadow passwd shadow; do
4380+ # the passwd from core without root
4381+ grep -v "^root:" "$UNPACK_DIR/etc/$f" > /mnt/system-data/root/test-etc/"$f"
4382+ # append this systems root user so that linode can connect
4383+ grep "^root:" /etc/"$f" >> /mnt/system-data/root/test-etc/"$f"
4384+
4385+ # make sure the group is as expected
4386+ chgrp --reference "$UNPACK_DIR/etc/$f" /mnt/system-data/root/test-etc/"$f"
4387+ # now bind mount read-only those passwd files on boot
4388+ cat >/mnt/system-data/etc/systemd/system/etc-"$f".mount <<EOF
4389+[Unit]
4390+Description=Mount root/test-etc/$f over system etc/$f
4391+Before=ssh.service
4392+
4393+[Mount]
4394+What=/root/test-etc/$f
4395+Where=/etc/$f
4396+Type=none
4397+Options=bind,ro
4398+
4399+[Install]
4400+WantedBy=multi-user.target
4401+EOF
4402+ ln -s /etc/systemd/system/etc-"$f".mount /mnt/system-data/etc/systemd/system/multi-user.target.wants/etc-"$f".mount
4403+
4404+ # create /var/lib/extrausers/$f
4405+ # append ubuntu, test user for the testing
4406+ grep "^test:" /etc/$f >> /mnt/system-data/var/lib/extrausers/"$f"
4407+ grep "^ubuntu:" /etc/$f >> /mnt/system-data/var/lib/extrausers/"$f"
4408+ # check test was copied
4409+ MATCH "^test:" </mnt/system-data/var/lib/extrausers/"$f"
4410+ MATCH "^ubuntu:" </mnt/system-data/var/lib/extrausers/"$f"
4411+ done
4412+
4413+ # ensure spread -reuse works in the core image as well
4414+ if [ -e /.spread.yaml ]; then
4415+ cp -av /.spread.yaml /mnt/system-data
4416+ fi
4417+
4418+ # using symbolic names requires test:test have the same ids
4419+ # inside and outside which is a pain (see 12345 above), but
4420+ # using the ids directly is the wrong kind of fragile
4421+ chown --verbose test:test /mnt/user-data/test
4422+
4423+ # we do what sync-dirs is normally doing on boot, but because
4424+ # we have subdirs/files in /etc/systemd/system (created below)
4425+ # the writeable-path sync-boot won't work
4426+ mkdir -p /mnt/system-data/etc/systemd
4427+
4428+ (cd /tmp ; unsquashfs -no-progress -v /var/lib/snapd/snaps/"$core_name"_*.snap etc/systemd/system)
4429+ cp -avr /tmp/squashfs-root/etc/systemd/system /mnt/system-data/etc/systemd/
4430+ umount /mnt
4431+ kpartx -d "$IMAGE_HOME/$IMAGE"
4432+
4433+ # the reflash magic
4434+ # FIXME: ideally in initrd, but this is good enough for now
4435+ cat > "$IMAGE_HOME/reflash.sh" << EOF
4436+#!/bin/sh -ex
4437+mount -t tmpfs none /tmp
4438+cp /bin/busybox /tmp
4439+cp $IMAGE_HOME/$IMAGE /tmp
4440+sync
4441+# blow away everything
4442+/tmp/busybox dd if=/tmp/$IMAGE of=/dev/sda bs=4M
4443+# and reboot
4444+/tmp/busybox sync
4445+/tmp/busybox echo b > /proc/sysrq-trigger
4446+EOF
4447+ chmod +x "$IMAGE_HOME/reflash.sh"
4448+
4449+ # extract ROOT from /proc/cmdline
4450+ ROOT=$(sed -e 's/^.*root=//' -e 's/ .*$//' /proc/cmdline)
4451+ cat >/boot/grub/grub.cfg <<EOF
4452+set default=0
4453+set timeout=2
4454+menuentry 'flash-all-snaps' {
4455+linux /vmlinuz root=$ROOT ro init=$IMAGE_HOME/reflash.sh console=ttyS0
4456+initrd /initrd.img
4457+}
4458+EOF
4459+}
4460+
4461+# prepare_ubuntu_core will prepare ubuntu-core 16 and 18
4462+prepare_ubuntu_core() {
4463+ # we are still a "classic" image, prepare the surgery
4464+ if [ -e /var/lib/dpkg/status ]; then
4465+ setup_reflash_magic
4466+ REBOOT
4467+ fi
4468+
4469+ # verify after the first reboot that we are now in core18 world
4470+ if [ "$SPREAD_REBOOT" = 1 ]; then
4471+ echo "Ensure we are now in an all-snap world"
4472+ if [ -e /var/lib/dpkg/status ]; then
4473+ echo "Rebooting into all-snap system did not work"
4474+ exit 1
4475+ fi
4476+ fi
4477+
4478+ echo "Wait for firstboot change to be ready"
4479+ while ! snap changes | grep "Done"; do
4480+ snap changes || true
4481+ snap change 1 || true
4482+ sleep 1
4483+ done
4484+
4485+ echo "Ensure fundamental snaps are still present"
4486+ # shellcheck source=tests/lib/names.sh
4487+ . "$TESTSLIB/names.sh"
4488+ for name in "$gadget_name" "$kernel_name" "$core_name"; do
4489+ if ! snap list "$name"; then
4490+ echo "Not all fundamental snaps are available, all-snap image not valid"
4491+ echo "Currently installed snaps"
4492+ snap list
4493+ exit 1
4494+ fi
4495+ done
4496+
4497+ echo "Ensure the snapd snap is available"
4498+ if is_core18_system; then
4499+ if ! snap list snapd; then
4500+ echo "snapd snap on core18 is missing"
4501+ snap list
4502+ exit 1
4503+ fi
4504+ fi
4505+
4506+ echo "Ensure rsync is available"
4507+ if ! command -v rsync; then
4508+ rsync_snap="test-snapd-rsync"
4509+ if is_core18_system; then
4510+ rsync_snap="test-snapd-rsync-core18"
4511+ fi
4512+ snap install --devmode "$rsync_snap"
4513+ snap alias "$rsync_snap".rsync rsync
4514+ fi
4515+
4516+ disable_refreshes
4517+ setup_systemd_snapd_overrides
4518+
4519+ # Snapshot the fresh state (including boot/bootenv)
4520+ if ! is_snapd_state_saved; then
4521+ systemctl stop snapd.service snapd.socket
4522+ save_snapd_state
4523+ systemctl start snapd.socket
4524+ fi
4525+
4526+ disable_kernel_rate_limiting
4527+}
4528diff --git a/tests/lib/quiet.sh b/tests/lib/quiet.sh
4529new file mode 100644
4530index 0000000..ef47b46
4531--- /dev/null
4532+++ b/tests/lib/quiet.sh
4533@@ -0,0 +1,30 @@
4534+#!/bin/bash
4535+
4536+# use "quiet foo" when you expect "foo" to produce a lot of output
4537+# that isn't useful unless foo itself fails.
4538+quiet() (
4539+ # note this is a subshell (parens instead of braces around the function)
4540+ # so this set only affects this function and not the caller
4541+ { set +x; } >&/dev/null
4542+
4543+ # not strictly needed because it's a subshell, but good practice
4544+ local tf retval
4545+
4546+ tf="$(mktemp)"
4547+
4548+ set +e
4549+ "$@" >& "$tf"
4550+ retval=$?
4551+ set -e
4552+
4553+ if [ "$retval" != "0" ]; then
4554+ echo "quiet: $*" >&2
4555+ echo "quiet: exit status $retval. Output follows:" >&2
4556+ cat "$tf" >&2
4557+ echo "quiet: end of output." >&2
4558+ fi
4559+
4560+ rm -f -- "$tf"
4561+
4562+ return $retval
4563+)
4564diff --git a/tests/lib/ramdisk.sh b/tests/lib/ramdisk.sh
4565new file mode 100644
4566index 0000000..b0489d7
4567--- /dev/null
4568+++ b/tests/lib/ramdisk.sh
4569@@ -0,0 +1,8 @@
4570+#!/bin/bash
4571+
4572+setup_ramdisk(){
4573+ if [ ! -e /dev/ram0 ]; then
4574+ mknod -m 660 /dev/ram0 b 1 0
4575+ chown root.disk /dev/ram0
4576+ fi
4577+}
4578diff --git a/tests/lib/random.sh b/tests/lib/random.sh
4579new file mode 100644
4580index 0000000..b15fa81
4581--- /dev/null
4582+++ b/tests/lib/random.sh
4583@@ -0,0 +1,39 @@
4584+#!/bin/bash
4585+
4586+# Helpers for replacing the proper random number generator with faster, but less
4587+# secure one and restoring it back. See
4588+# http://elixir.free-electrons.com/linux/latest/source/Documentation/admin-guide/devices.txt
4589+# for major:minor assignments.
4590+
4591+kill_gpg_agent() {
4592+ # gpg-agent might have started before, need to kill it, normally we would
4593+ # call gpgconf --kill gpg-agent but this does not seem 100% reliable, try
4594+ # more direct approach; if gpg-agent gets blocked reading from /dev/random
4595+ # it will not react to SIGTERM, use SIGKILL instead
4596+ pkill -9 -e gpg-agent || true
4597+}
4598+
4599+fixup_dev_random() {
4600+ # keep the original /dev/random around
4601+ mv /dev/random /dev/random.orig
4602+ # same as /dev/urandom
4603+ mknod /dev/random c 1 9
4604+ # make sure that gpg-agent picks up the new device
4605+ kill_gpg_agent
4606+}
4607+
4608+restore_dev_random() {
4609+ if test -c /dev/random.orig ; then
4610+ mv /dev/random.orig /dev/random
4611+ fi
4612+}
4613+
4614+debug_random() {
4615+ sysctl kernel.random.entropy_avail || true
4616+ ls -l /dev/*random*
4617+ pids=$(pidof gpg-agent)
4618+ for p in $pids; do
4619+ ps -q "$p"
4620+ ls -l "/proc/$p/fd"
4621+ done
4622+}
4623diff --git a/tests/lib/reset.sh b/tests/lib/reset.sh
4624new file mode 100755
4625index 0000000..08917e4
4626--- /dev/null
4627+++ b/tests/lib/reset.sh
4628@@ -0,0 +1,148 @@
4629+#!/bin/bash
4630+
4631+set -e -x
4632+
4633+# shellcheck source=tests/lib/dirs.sh
4634+. "$TESTSLIB/dirs.sh"
4635+# shellcheck source=tests/lib/state.sh
4636+. "$TESTSLIB/state.sh"
4637+
4638+
4639+# shellcheck source=tests/lib/systemd.sh
4640+. "$TESTSLIB/systemd.sh"
4641+
4642+#shellcheck source=tests/lib/systems.sh
4643+. "$TESTSLIB"/systems.sh
4644+
4645+reset_classic() {
4646+ # Reload all service units as in some situations the unit might
4647+ # have changed on the disk.
4648+ systemctl daemon-reload
4649+
4650+ echo "Ensure the service is active before stopping it"
4651+ retries=20
4652+ systemctl status snapd.service snapd.socket || true
4653+ while systemctl status snapd.service snapd.socket | grep "Active: activating"; do
4654+ if [ $retries -eq 0 ]; then
4655+ echo "snapd service or socket not active"
4656+ exit 1
4657+ fi
4658+ retries=$(( retries - 1 ))
4659+ sleep 1
4660+ done
4661+
4662+ systemd_stop_units snapd.service snapd.socket
4663+
4664+ case "$SPREAD_SYSTEM" in
4665+ ubuntu-*|debian-*)
4666+ sh -x "${SPREAD_PATH}/debian/snapd.postrm" purge
4667+ ;;
4668+ fedora-*|opensuse-*|arch-*|amazon-*)
4669+ # We don't know if snap-mgmt was built, so call the *.in file
4670+ # directly and pass arguments that will override the placeholders
4671+ sh -x "${SPREAD_PATH}/cmd/snap-mgmt/snap-mgmt.sh.in" \
4672+ --snap-mount-dir="$SNAP_MOUNT_DIR" \
4673+ --purge
4674+ # The script above doesn't remove the snapd directory as this
4675+ # is normally done by the rpm packaging system.
4676+ rm -rf /var/lib/snapd
4677+ ;;
4678+ *)
4679+ exit 1
4680+ ;;
4681+ esac
4682+ # extra purge
4683+ rm -rvf /var/snap "${SNAP_MOUNT_DIR:?}/bin"
4684+ mkdir -p "$SNAP_MOUNT_DIR" /var/snap /var/lib/snapd
4685+ if [ "$(find "$SNAP_MOUNT_DIR" /var/snap -mindepth 1 -print -quit)" ]; then
4686+ echo "postinst purge failed"
4687+ ls -lR "$SNAP_MOUNT_DIR"/ /var/snap/
4688+ exit 1
4689+ fi
4690+
4691+ if [[ "$SPREAD_SYSTEM" == ubuntu-14.04-* ]]; then
4692+ systemctl start snap.mount.service
4693+ fi
4694+
4695+ rm -rf /root/.snap/gnupg
4696+ rm -f /tmp/core* /tmp/ubuntu-core*
4697+
4698+ if [ "$1" = "--reuse-core" ]; then
4699+ # Restore snapd state and start systemd service units
4700+ restore_snapd_state
4701+ escaped_snap_mount_dir="$(systemd-escape --path "$SNAP_MOUNT_DIR")"
4702+ mounts="$(systemctl list-unit-files --full | grep "^${escaped_snap_mount_dir}[-.].*\\.mount" | cut -f1 -d ' ')"
4703+ services="$(systemctl list-unit-files --full | grep "^${escaped_snap_mount_dir}[-.].*\\.service" | cut -f1 -d ' ')"
4704+ systemctl daemon-reload # Workaround for http://paste.ubuntu.com/17735820/
4705+ for unit in $mounts $services; do
4706+ systemctl start "$unit"
4707+ done
4708+
4709+ # force all profiles to be re-generated
4710+ rm -f /var/lib/snapd/system-key
4711+ fi
4712+
4713+ if [ "$1" != "--keep-stopped" ]; then
4714+ systemctl start snapd.socket
4715+
4716+ # wait for snapd listening
4717+ EXTRA_NC_ARGS="-q 1"
4718+ if [[ "$SPREAD_SYSTEM" = fedora-* || "$SPREAD_SYSTEM" = amazon-* ]]; then
4719+ EXTRA_NC_ARGS=""
4720+ fi
4721+ while ! printf 'GET / HTTP/1.0\r\n\r\n' | nc -U $EXTRA_NC_ARGS /run/snapd.socket; do sleep 0.5; done
4722+ fi
4723+}
4724+
4725+reset_all_snap() {
4726+ # remove all leftover snaps
4727+ # shellcheck source=tests/lib/names.sh
4728+ . "$TESTSLIB/names.sh"
4729+
4730+ remove_bases=""
4731+ # remove all app snaps first
4732+ for snap in "$SNAP_MOUNT_DIR"/*; do
4733+ snap="${snap:6}"
4734+ case "$snap" in
4735+ "bin" | "$gadget_name" | "$kernel_name" | "$core_name" | README)
4736+ ;;
4737+ *)
4738+ # make sure snapd is running before we attempt to remove snaps, in case a test stopped it
4739+ if ! systemctl status snapd.service snapd.socket; then
4740+ systemctl start snapd.service snapd.socket
4741+ fi
4742+ if ! echo "$SKIP_REMOVE_SNAPS" | grep -w "$snap"; then
4743+ if snap info "$snap" | egrep '^type: +(base|core)'; then
4744+ remove_bases="$remove_bases $snap"
4745+ else
4746+ snap remove "$snap"
4747+ fi
4748+ fi
4749+ ;;
4750+ esac
4751+ done
4752+ # remove all base/os snaps at the end
4753+ if [ -n "$remove_bases" ]; then
4754+ snap remove "$remove_bases"
4755+ fi
4756+
4757+ # ensure we have the same state as initially
4758+ systemctl stop snapd.service snapd.socket
4759+ restore_snapd_state
4760+ rm -rf /root/.snap
4761+ if [ "$1" != "--keep-stopped" ]; then
4762+ systemctl start snapd.service snapd.socket
4763+ fi
4764+}
4765+
4766+if is_core_system; then
4767+ reset_all_snap "$@"
4768+else
4769+ reset_classic "$@"
4770+fi
4771+
4772+if [ "$REMOTE_STORE" = staging ] && [ "$1" = "--store" ]; then
4773+ # shellcheck source=tests/lib/store.sh
4774+ . "$TESTSLIB"/store.sh
4775+ teardown_staging_store
4776+fi
4777diff --git a/tests/lib/snaps.sh b/tests/lib/snaps.sh
4778new file mode 100644
4779index 0000000..614d8d9
4780--- /dev/null
4781+++ b/tests/lib/snaps.sh
4782@@ -0,0 +1,85 @@
4783+#!/bin/bash
4784+
4785+make_snap() {
4786+ local SNAP_NAME="$1"
4787+ shift;
4788+ local SNAP_FILE="$TESTSLIB/snaps/${SNAP_NAME}/${SNAP_NAME}_1.0_all.snap"
4789+ local SNAP_DIR
4790+ # assigned in a separate step to avoid hiding a failure
4791+ SNAP_DIR="$(dirname "$SNAP_FILE")"
4792+ if [ ! -f "$SNAP_FILE" ]; then
4793+ snap pack "$SNAP_DIR" "$SNAP_DIR" >/dev/null
4794+ fi
4795+ # echo the snap name
4796+ if [ -f "$SNAP_FILE" ]; then
4797+ echo "$SNAP_FILE"
4798+ else
4799+ find "$TESTSLIB/snaps/${SNAP_NAME}" -name '*.snap' | head -n1
4800+ fi
4801+}
4802+
4803+install_local() {
4804+ local SNAP_NAME="$1"
4805+ shift
4806+ SNAP_FILE=$(make_snap "$SNAP_NAME")
4807+
4808+ snap install --dangerous "$@" "$SNAP_FILE"
4809+}
4810+
4811+install_local_devmode() {
4812+ install_local "$1" --devmode
4813+}
4814+
4815+install_local_classic() {
4816+ install_local "$1" --classic
4817+}
4818+
4819+install_local_jailmode() {
4820+ install_local "$1" --jailmode
4821+}
4822+
4823+# mksnap_fast creates a snap using a faster compress algorithm (gzip)
4824+# than the regular snaps (which are lzma)
4825+mksnap_fast() {
4826+ dir="$1"
4827+ snap="$2"
4828+
4829+ case "$SPREAD_SYSTEM" in
4830+ ubuntu-14.04-*|amazon-*)
4831+ # trusty and AMZN2 do not support -Xcompression-level 1
4832+ mksquashfs "$dir" "$snap" -comp gzip -no-fragments -no-progress
4833+ ;;
4834+ *)
4835+ mksquashfs "$dir" "$snap" -comp gzip -Xcompression-level 1 -no-fragments -no-progress
4836+ ;;
4837+ esac
4838+}
4839+
4840+install_generic_consumer() {
4841+ local INTERFACE_NAME="$1"
4842+ cp -ar "$TESTSLIB/snaps/generic-consumer" .
4843+ sed "s/@INTERFACE@/$INTERFACE_NAME/" generic-consumer/meta/snap.yaml.in > generic-consumer/meta/snap.yaml
4844+ snap pack generic-consumer generic-consumer
4845+ snap install --dangerous generic-consumer/*.snap
4846+ rm -rf generic-consumer
4847+}
4848+
4849+is_classic_confinement_supported() {
4850+ case "$SPREAD_SYSTEM" in
4851+ ubuntu-core-16-*)
4852+ return 1
4853+ ;;
4854+ ubuntu-*|debian-*)
4855+ return 0
4856+ ;;
4857+ fedora-*)
4858+ return 1
4859+ ;;
4860+ opensuse-*)
4861+ return 0
4862+ ;;
4863+ *)
4864+ return 0
4865+ ;;
4866+ esac
4867+}
4868diff --git a/tests/lib/snaps/account-control-consumer/bin/chpasswd b/tests/lib/snaps/account-control-consumer/bin/chpasswd
4869new file mode 100755
4870index 0000000..e90ec83
4871--- /dev/null
4872+++ b/tests/lib/snaps/account-control-consumer/bin/chpasswd
4873@@ -0,0 +1,3 @@
4874+#!/bin/sh
4875+
4876+exec /usr/sbin/chpasswd "$@"
4877diff --git a/tests/lib/snaps/account-control-consumer/bin/deluser b/tests/lib/snaps/account-control-consumer/bin/deluser
4878new file mode 100755
4879index 0000000..10797bc
4880--- /dev/null
4881+++ b/tests/lib/snaps/account-control-consumer/bin/deluser
4882@@ -0,0 +1,3 @@
4883+#!/bin/sh
4884+
4885+exec /usr/sbin/deluser "$@"
4886diff --git a/tests/lib/snaps/account-control-consumer/bin/useradd b/tests/lib/snaps/account-control-consumer/bin/useradd
4887new file mode 100755
4888index 0000000..f4ae98e
4889--- /dev/null
4890+++ b/tests/lib/snaps/account-control-consumer/bin/useradd
4891@@ -0,0 +1,3 @@
4892+#!/bin/sh
4893+
4894+exec /usr/sbin/useradd "$@"
4895diff --git a/tests/lib/snaps/account-control-consumer/meta/snap.yaml b/tests/lib/snaps/account-control-consumer/meta/snap.yaml
4896new file mode 100644
4897index 0000000..190cfc7
4898--- /dev/null
4899+++ b/tests/lib/snaps/account-control-consumer/meta/snap.yaml
4900@@ -0,0 +1,15 @@
4901+name: account-control-consumer
4902+version: 1.0
4903+summary: Basic account-control consumer snap
4904+description: A basic snap declaring a plug on a account-control slot
4905+
4906+apps:
4907+ useradd:
4908+ command: bin/useradd
4909+ plugs: [account-control]
4910+ deluser:
4911+ command: bin/deluser
4912+ plugs: [account-control]
4913+ chpasswd:
4914+ command: bin/chpasswd
4915+ plugs: [account-control]
4916diff --git a/tests/lib/snaps/aliases/bin/cmd1 b/tests/lib/snaps/aliases/bin/cmd1
4917new file mode 100755
4918index 0000000..b33dea5
4919--- /dev/null
4920+++ b/tests/lib/snaps/aliases/bin/cmd1
4921@@ -0,0 +1,2 @@
4922+#!/bin/sh
4923+echo "ok command 1"
4924diff --git a/tests/lib/snaps/aliases/bin/cmd2 b/tests/lib/snaps/aliases/bin/cmd2
4925new file mode 100755
4926index 0000000..265d412
4927--- /dev/null
4928+++ b/tests/lib/snaps/aliases/bin/cmd2
4929@@ -0,0 +1,2 @@
4930+#!/bin/sh
4931+echo "ok command 2"
4932diff --git a/tests/lib/snaps/aliases/meta/icon.png b/tests/lib/snaps/aliases/meta/icon.png
4933new file mode 100644
4934index 0000000..1ec92f1
4935Binary files /dev/null and b/tests/lib/snaps/aliases/meta/icon.png differ
4936diff --git a/tests/lib/snaps/aliases/meta/snap.yaml b/tests/lib/snaps/aliases/meta/snap.yaml
4937new file mode 100644
4938index 0000000..fb52b20
4939--- /dev/null
4940+++ b/tests/lib/snaps/aliases/meta/snap.yaml
4941@@ -0,0 +1,9 @@
4942+name: aliases
4943+version: 1.0
4944+apps:
4945+ cmd1:
4946+ command: bin/cmd1
4947+ aliases: [alias1]
4948+ cmd2:
4949+ command: bin/cmd2
4950+ aliases: [alias2]
4951diff --git a/tests/lib/snaps/basic-desktop/bin/echo b/tests/lib/snaps/basic-desktop/bin/echo
4952new file mode 100755
4953index 0000000..ce4b344
4954--- /dev/null
4955+++ b/tests/lib/snaps/basic-desktop/bin/echo
4956@@ -0,0 +1,3 @@
4957+#!/bin/sh
4958+
4959+echo "From basic-desktop snap"
4960diff --git a/tests/lib/snaps/basic-desktop/meta/gui/echo.desktop b/tests/lib/snaps/basic-desktop/meta/gui/echo.desktop
4961new file mode 100644
4962index 0000000..932e2e5
4963--- /dev/null
4964+++ b/tests/lib/snaps/basic-desktop/meta/gui/echo.desktop
4965@@ -0,0 +1,10 @@
4966+[Desktop Entry]
4967+Name=Echo
4968+Comment=It echos stuff
4969+Exec=basic-desktop.echo
4970+Icon=${SNAP}/meta/gui/icon.png
4971+Terminal=true
4972+Type=Application
4973+Categories=Utilities;Useless;
4974+Keywords=echo;echo;
4975+StartupNotify=false
4976diff --git a/tests/lib/snaps/basic-desktop/meta/gui/icon.png b/tests/lib/snaps/basic-desktop/meta/gui/icon.png
4977new file mode 100644
4978index 0000000..1ec92f1
4979Binary files /dev/null and b/tests/lib/snaps/basic-desktop/meta/gui/icon.png differ
4980diff --git a/tests/lib/snaps/basic-desktop/meta/snap.yaml b/tests/lib/snaps/basic-desktop/meta/snap.yaml
4981new file mode 100644
4982index 0000000..df8621e
4983--- /dev/null
4984+++ b/tests/lib/snaps/basic-desktop/meta/snap.yaml
4985@@ -0,0 +1,6 @@
4986+name: basic-desktop
4987+version: 1.0
4988+license: GPL-3.0
4989+apps:
4990+ echo:
4991+ command: bin/echo
4992diff --git a/tests/lib/snaps/basic-hooks/meta/hooks/configure b/tests/lib/snaps/basic-hooks/meta/hooks/configure
4993new file mode 100755
4994index 0000000..a9ec5e0
4995--- /dev/null
4996+++ b/tests/lib/snaps/basic-hooks/meta/hooks/configure
4997@@ -0,0 +1,7 @@
4998+#!/bin/sh
4999+
5000+echo "configure hook"
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches