Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run Chip Tool without sudo #55

Merged
merged 10 commits into from
Jun 13, 2024
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ sudo snap connect chip-tool:process-control
### Commissioning into IP network
Discover using DNS-SD and pair:
```bash
sudo chip-tool pairing onnetwork 110 20202021
chip-tool pairing onnetwork 110 20202021
```

where:
Expand All @@ -56,7 +56,7 @@ Done

Discover and pair:
```bash
sudo chip-tool pairing ble-thread 110 hex:0e08...f7f8 20202021 3840
chip-tool pairing ble-thread 110 hex:0e08...f7f8 20202021 3840
```

where:
Expand All @@ -70,7 +70,7 @@ where:
### Control
Toggle:
```bash
sudo chip-tool onoff toggle 110 1
chip-tool onoff toggle 110 1
```

where:
Expand All @@ -81,6 +81,27 @@ where:
- `1` is the endpoint of the configured device


### Note on sudo

The latest version of the chip-tool snap does not require the use of sudo (root access). If you have updated the snap from a previous version it will still work with sudo. If you run it as a normal user, the previous state of provisioned devices will not be available.

To change from running with sudo to running without sudo, you need to copy the database files from the root user to your user, and update the file ownerships. This can be done with these two commands:

```
sudo cp /var/snap/chip-tool/common/mnt/chip_tool_* ~/snap/chip-tool/common/
sudo chown $USER:$USER ~/snap/chip-tool/common/*
```

If you run chip-tool again without sudo and get an error similar to `CHIP Error 0x000000AF: Write to file failed`, either restart your computer to clear all temporary files, or run the following commands to delete them:

```
# Open a shell inside the chip-tool snap sandbox
sudo snap run --shell chip-tool.chip-tool
# Inside this shell, delete the temporary files
rm /tmp/chip_*
```


## Build

Build locally for the architecture same as the host:
Expand Down
8 changes: 8 additions & 0 deletions snap/hooks/post-refresh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

# This script runs as root, so $SNAP_USER_COMMON is /root/snap/chip-tool/common
# See https://forum.snapcraft.io/t/snapcraft-hook-support/19069/12

if [ -d $SNAP_COMMON/mnt ] && [ -n "$(ls -A $SNAP_COMMON/mnt)" ]; then
cp $SNAP_COMMON/mnt/* $SNAP_USER_COMMON/;
fi
5 changes: 5 additions & 0 deletions snap/local/bin/set-tmp-dir.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

export TMPDIR=$SNAP_USER_COMMON

exec "$@"
31 changes: 7 additions & 24 deletions snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ architectures:
- build-on: amd64
- build-on: arm64

layout:
/mnt:
bind: $SNAP_COMMON/mnt

parts:
local:
plugin: nil
source: snap/local
override-build: |
cp -rv bin $SNAPCRAFT_PART_INSTALL/

connectedhomeip:
plugin: nil
build-environment:
Expand All @@ -40,23 +42,6 @@ parts:
mkdir -p $CRAFT_PART_INSTALL/bin

cd ../../connectedhomeip/src

# The project writes its data to /tmp which isn't persisted.
#
# Setting TMPDIR env var when running the app isn't sufficient as
# chip_[config,counter,factory,kvs].ini still get written under /tmp.
# The chip-tool currently has no way of overriding the default paths to
# storage and security config files.
#
# Snap does not allow bind mounting a persistent directory on /tmp,
# so we need to replace it in the source with another path, e.g. /mnt.
# See the top-level layout definition which bind mounts a persisted
# directory within the confined snap space on /mnt.
#
# Replace storage paths:
sed -i 's/\/tmp/\/mnt/g' src/platform/Linux/CHIPLinuxStorage.h
# Replace key-value store path:
sed -i 's/\/tmp/\/mnt/g' src/platform/Linux/CHIPPlatformConfig.h

# To avoid activation errors, don't treat unset variables as error
set +u
Expand Down Expand Up @@ -88,13 +73,11 @@ parts:

apps:
chip-tool:
command-chain: [bin/set-tmp-dir.sh]
command: bin/chip-tool
plugs:
- network
- network-bind
- bluez
- avahi-observe
- process-control
environment:
# Replace the path for chip-tool configuration files
TMPDIR: "/mnt"
4 changes: 3 additions & 1 deletion tests/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import (
"github.com/stretchr/testify/require"
)

const allClusterSnap = "matter-all-clusters-app"
jpm-canonical marked this conversation as resolved.
Show resolved Hide resolved
const chipToolSnap = "chip-tool"

func InstallChipTool(t *testing.T) {
const chipToolSnap = "chip-tool"

// clean
utils.SnapRemove(t, chipToolSnap)
Expand Down
93 changes: 93 additions & 0 deletions tests/upgrade_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package tests

import (
"github.com/canonical/matter-snap-testing/utils"
"github.com/stretchr/testify/assert"
"log"
"os"
"testing"
"time"
)

func TestUpgrade(t *testing.T) {
start := time.Now()

// Remove snaps and logs at end of test, even if it failed
t.Cleanup(func() {
utils.SnapRemove(nil, allClusterSnap)
utils.SnapDumpLogs(nil, start, allClusterSnap)
utils.SnapRemove(nil, chipToolSnap)
utils.SnapDumpLogs(nil, start, chipToolSnap)
})

// Start clean
utils.SnapRemove(t, allClusterSnap)
utils.SnapRemove(t, chipToolSnap)

// Install stable chip tool from store
utils.SnapInstallFromStore(t, chipToolSnap, "latest/stable")

// Setup chip-tool
utils.SnapConnect(t, chipToolSnap+":avahi-observe", "")
utils.SnapConnect(t, chipToolSnap+":bluez", "")
utils.SnapConnect(t, chipToolSnap+":process-control", "")

// Install all clusters app
utils.SnapInstallFromStore(t, allClusterSnap, utils.ServiceChannel)

// Setup all clusters app
utils.SnapSet(t, allClusterSnap, "args", "--wifi")
utils.SnapConnect(t, allClusterSnap+":avahi-control", "")
utils.SnapConnect(t, allClusterSnap+":bluez", "")

// Start all clusters app
utils.SnapStart(t, allClusterSnap)
utils.WaitForLogMessage(t,
allClusterSnap, "CHIP minimal mDNS started advertising", start)

// Pair device
t.Run("Commission", func(t *testing.T) {
stdout, _, _ := utils.Exec(t, "sudo chip-tool pairing onnetwork 110 20202021 2>&1")
assert.NoError(t,
os.WriteFile("chip-tool-pairing.log", []byte(stdout), 0644),
)
})

// Control device
t.Run("Control with stable snap", func(t *testing.T) {
snapVersion := utils.SnapVersion(t, chipToolSnap)
snapRevision := utils.SnapRevision(t, chipToolSnap)
log.Printf("%s installed version %s build %s\n", chipToolSnap, snapVersion, snapRevision)

stdout, _, _ := utils.Exec(t, "sudo chip-tool onoff toggle 110 1 2>&1")
assert.NoError(t,
os.WriteFile("chip-tool-onoff.log", []byte(stdout), 0644),
)

utils.WaitForLogMessage(t,
allClusterSnap, "CHIP:ZCL: Toggle ep1 on/off", start)
})

// Upgrade chip-tool to local snap or edge
if utils.LocalServiceSnap() {
utils.SnapInstallFromFile(t, utils.LocalServiceSnapPath)
} else {
utils.SnapRefresh(t, chipToolSnap, "latest/edge")
}

// Control device again
t.Run("Control upgraded snap", func(t *testing.T) {
snapVersion := utils.SnapVersion(t, chipToolSnap)
snapRevision := utils.SnapRevision(t, chipToolSnap)
log.Printf("%s installed version %s build %s\n", chipToolSnap, snapVersion, snapRevision)

stdout, _, _ := utils.Exec(t, "sudo chip-tool onoff toggle 110 1 2>&1")
assert.NoError(t,
os.WriteFile("chip-tool-onoff.log", []byte(stdout), 0644),
)

utils.WaitForLogMessage(t,
allClusterSnap, "CHIP:ZCL: Toggle ep1 on/off", start)
})

}
2 changes: 0 additions & 2 deletions tests/wifi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/stretchr/testify/assert"
)

const allClusterSnap = "matter-all-clusters-app"

func TestAllClustersAppWiFi(t *testing.T) {
InstallChipTool(t)

Expand Down
Loading