Giter VIP home page Giter VIP logo

chip-tool-snap's Introduction

Chip Tool Snap

chip-tool

Chip Tool is a Matter controller being developed as part of the Connected Home IP project.

The snap packaging makes it easy to run the Chip Tool on Linux distributions.

This snap has been tested on amd64/arm64 architectures for WiFi/Ethernet/DNS-SD/BLE/Thread commissioning and control.

Usage

Setup

sudo snap install chip-tool

Connect the avahi-observe interface to allow DNS-SD based discovery:

sudo snap connect chip-tool:avahi-observe

Connect the bluez interface for device discovery over Bluetooth Low Energy (BLE):

sudo snap connect chip-tool:bluez

Connect the process-control interface for system-wide process management. This is needed to grant Chip Tool access to make sched_setattr system calls. This may improve the reliability of the operations (see #8).

sudo snap connect chip-tool:process-control

Note
On Ubuntu Core, the avahi-observe and bluez interfaces are not provided by the system.

These interfaces are provided by other snaps, such as the Avahi and BlueZ snaps. To install the snaps and connect to the interfaces, run:

sudo snap install avahi bluez
sudo snap connect chip-tool:avahi-observe avahi:avahi-observe
sudo snap connect chip-tool:bluez bluez:service

Commissioning into IP network

Discover using DNS-SD and pair:

sudo chip-tool pairing onnetwork 110 20202021

where:

  • 110 is the node id being assigned to the app
  • 20202021 is the pin code set on the app

Commissioning into Thread network over BLE

This depends on an OpenThread Border Router (OTBR) with an active network. For guidance on setting that up using the OTBR snap, refer to this tutorial.

Use the OpenThread CLI to obtain Thread network credential:

$ sudo ot-ctl dataset active -x
0e08...f7f8
Done

Discover and pair:

sudo chip-tool pairing ble-thread 110 hex:0e08...f7f8 20202021 3840

where:

  • 110 is the node id being assigned to the app
  • 0e08...f7f8 is the Thread network credential operational dataset, truncated for readability.
  • 20202021 is the pin code set on the app
  • 3840 is the discriminator id

Control

Toggle:

sudo chip-tool onoff toggle 110 1

where:

  • onoff is the matter cluster name
  • on/off/toggle is the command name.
  • 110 is the node id of the app assigned during the commissioning
  • 1 is the endpoint of the configured device

Build

Build locally for the architecture same as the host:

snapcraft -v

Build remotely for all supported architectures:

snapcraft remote-build

Test

Refer to tests.

chip-tool-snap's People

Contributors

farshidtz avatar locnnil avatar monicaisher avatar prash813 avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

chip-tool-snap's Issues

Make chip-tool command work without root privileges

The chip-tool command installed by the snap requires root privileges to function. This is because the storage and config files are written under /mnt, which is bind mounted on /var/snap/chip-tool/common/mnt/. This directory is owned by the root user.

This also makes it problematic to use the tool independently with different users.

Ideally, the storage and config paths should be user specific (e.g. read from SNAP_USER_COMMON). This is currently not easily achievable since the paths are set at compile time.

Document the timeout extension for commissioning Thread device into Thread network

During the testing of matter-pi-gpio-commander, it was discovered that chip-tool encountered trouble commissioning the commander snap via the Thread feature. This comment also confirms that the Thread commission error might originate from chip-tool, considering that the Python Matter Server in Home Assistant Libs can commission the commander snap. Here is the log from chip-tool:

$ sudo chip-tool pairing ble-thread 110 hex:0e080000000000010000000300000c35060004001fffe00208d2f97acbb3662c9b0708fda12b93c2ba31520510fc408c0ff8d558aa52617ba63a435417030f4f70656e5468726561642d303235380102025804101ef3e9682c1d382dee42aec736a1c23b0c0402a0f7f8 20202021 3840
[1701099866.706623][82231:82231] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /mnt/chip_tool_kvs
[1701099866.706841][82231:82231] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /mnt/chip_kvs
[1701099866.706845][82231:82231] CHIP:DL: ChipLinuxStorage::Init: Attempt to re-initialize with KVS config file: /mnt/chip_kvs
[1701099866.707927][82231:82231] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /mnt/chip_factory.ini
[1701099866.707952][82231:82231] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /mnt/chip_config.ini
[1701099866.707960][82231:82231] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /mnt/chip_counters.ini
[1701099866.708015][82231:82231] CHIP:DL: writing settings to file (/mnt/chip_counters.ini-p2fLEu)
[1701099866.708102][82231:82231] CHIP:DL: renamed tmp file to file (/mnt/chip_counters.ini)
[1701099866.708107][82231:82231] CHIP:DL: NVS set: chip-counters/reboot-count = 27 (0x1B)
[1701099866.708324][82231:82231] CHIP:DL: Got Ethernet interface: eno1
[1701099866.708471][82231:82231] CHIP:DL: Found the primary Ethernet interface:eno1
[1701099866.708685][82231:82231] CHIP:DL: Failed to get WiFi interface
[1701099866.708687][82231:82231] CHIP:DL: Failed to reset WiFi statistic counts
[1701099866.708695][82231:82231] CHIP:IN: UDP::Init bind&listen port=0
[1701099866.708707][82231:82231] CHIP:IN: UDP::Init bound to port=42743
[1701099866.708708][82231:82231] CHIP:IN: UDP::Init bind&listen port=0
[1701099866.708715][82231:82231] CHIP:IN: UDP::Init bound to port=51228
[1701099866.708717][82231:82231] CHIP:IN: BLEBase::Init - setting/overriding transport
[1701099866.708718][82231:82231] CHIP:IN: TransportMgr initialized
[1701099866.708723][82231:82231] CHIP:FP: Initializing FabricTable from persistent storage
[1701099866.708750][82231:82231] CHIP:TS: Last Known Good Time: 2023-10-14T01:16:48
[1701099866.709037][82231:82231] CHIP:FP: Fabric index 0x1 was retrieved from storage. Compressed FabricId 0xE6CACD9207E74AF0, FabricId 0x0000000000000001, NodeId 0x000000000001B669, VendorId 0xFFF1
[1701099866.709241][82231:82231] CHIP:ZCL: Using ZAP configuration...
[1701099866.711916][82231:82231] CHIP:CTL: System State Initialized...
[1701099866.711946][82231:82231] CHIP:CTL: Setting attestation nonce to random value
[1701099866.711951][82231:82231] CHIP:CTL: Setting CSR nonce to random value
[1701099866.711959][82231:82231] CHIP:IN: UDP::Init bind&listen port=5550
[1701099866.711966][82231:82231] CHIP:IN: UDP::Init bound to port=5550
[1701099866.711968][82231:82231] CHIP:IN: UDP::Init bind&listen port=5550
[1701099866.711974][82231:82231] CHIP:IN: UDP::Init bound to port=5550
[1701099866.711976][82231:82231] CHIP:IN: TransportMgr initialized
[1701099866.712045][82231:82259] CHIP:DL: CHIP task running
[1701099866.712060][82231:82259] CHIP:DL: HandlePlatformSpecificBLEEvent 32784
[1701099866.712140][82231:82259] CHIP:CTL: Setting attestation nonce to random value
[1701099866.712159][82231:82259] CHIP:CTL: Setting CSR nonce to random value
[1701099866.712329][82231:82259] CHIP:CTL: Generating NOC
[1701099866.712507][82231:82259] CHIP:FP: Validating NOC chain
[1701099866.712800][82231:82259] CHIP:FP: NOC chain validation successful
[1701099866.712830][82231:82259] CHIP:FP: Updated fabric at index: 0x1, Node ID: 0x000000000001B669
[1701099866.712833][82231:82259] CHIP:TS: Last Known Good Time: 2023-10-14T01:16:48
[1701099866.712834][82231:82259] CHIP:TS: New proposed Last Known Good Time: 2021-01-01T00:00:00
[1701099866.712835][82231:82259] CHIP:TS: Retaining current Last Known Good Time
[1701099866.713070][82231:82259] CHIP:FP: Metadata for Fabric 0x1 persisted to storage.
[1701099866.713226][82231:82259] CHIP:TS: Committing Last Known Good Time to storage: 2023-10-14T01:16:48
[1701099866.713366][82231:82259] CHIP:CTL: Joined the fabric at index 1. Fabric ID is 0x0000000000000001 (Compressed Fabric ID: E6CACD9207E74AF0)
[1701099866.713370][82231:82259] CHIP:IN: UDP::Init bind&listen port=5550
[1701099866.713382][82231:82259] CHIP:IN: UDP::Init bound to port=5550
[1701099866.713383][82231:82259] CHIP:IN: UDP::Init bind&listen port=5550
[1701099866.713390][82231:82259] CHIP:IN: UDP::Init bound to port=5550
[1701099866.713392][82231:82259] CHIP:IN: TransportMgr initialized
[1701099866.714959][82231:82259] CHIP:CTL: Setting thread operational dataset from parameters
[1701099866.714962][82231:82259] CHIP:CTL: Setting attestation nonce to random value
[1701099866.714967][82231:82259] CHIP:CTL: Setting CSR nonce to random value
[1701099866.714970][82231:82259] CHIP:CTL: Commission called for node ID 0x000000000000006E
[1701099866.715954][82231:82258] CHIP:DL: TRACE: Bus acquired for name C-4137
[1701099866.717564][82231:82259] CHIP:DL: PlatformBlueZInit init success
[1701099866.719161][82231:82258] CHIP:BLE: BLE removing known devices.
[1701099866.719617][82231:82258] CHIP:BLE: BLE initiating scan.
[1701099866.867459][82231:82258] CHIP:BLE: Device 5A:C8:D3:99:E0:C4 does not look like a CHIP device.
...
[1701099876.783735][82231:82258] CHIP:BLE: Device E0:58:7C:A2:D7:11 does not look like a CHIP device.
[1701099876.794460][82231:82259] CHIP:DIS: Closing all BLE connections
[1701099876.794516][82231:82259] CHIP:TOO: Pairing Failure: src/platform/Linux/bluez/ChipDeviceScanner.cpp:173: CHIP Error 0x00000032: Timeout
[1701099876.794546][82231:82259] CHIP:BLE: BLE scan error: src/platform/Linux/bluez/ChipDeviceScanner.cpp:173: CHIP Error 0x00000032: Timeout
[1701099876.798313][82231:82259] CHIP:BLE: Scan complete. No matching device found.
[1701099876.798514][82231:82231] CHIP:CTL: Shutting down the commissioner
[1701099876.798595][82231:82231] CHIP:CTL: Shutting down the controller
[1701099876.798636][82231:82231] CHIP:IN: Expiring all sessions for fabric 0x1!!
[1701099876.798651][82231:82231] CHIP:FP: Forgetting fabric 0x1
[1701099876.798676][82231:82231] CHIP:TS: Pending Last Known Good Time: 2023-10-14T01:16:48
[1701099876.798817][82231:82231] CHIP:TS: Previous Last Known Good Time: 2023-10-14T01:16:48
[1701099876.798828][82231:82231] CHIP:TS: Reverted Last Known Good Time to previous value
[1701099876.798867][82231:82231] CHIP:CTL: Shutting down the commissioner
[1701099876.798910][82231:82231] CHIP:CTL: Shutting down the controller
[1701099876.798922][82231:82231] CHIP:CTL: Shutting down the System State, this will teardown the CHIP Stack
[1701099876.799119][82231:82231] CHIP:DMG: All ReadHandler-s are clean, clear GlobalDirtySet
[1701099876.799177][82231:82231] CHIP:FP: Shutting down FabricTable
[1701099876.799192][82231:82231] CHIP:TS: Pending Last Known Good Time: 2023-10-14T01:16:48
[1701099876.799294][82231:82231] CHIP:TS: Previous Last Known Good Time: 2023-10-14T01:16:48
[1701099876.799307][82231:82231] CHIP:TS: Reverted Last Known Good Time to previous value
[1701099876.799589][82231:82231] CHIP:DL: writing settings to file (/mnt/chip_counters.ini-35CMQo)
[1701099876.799997][82231:82231] CHIP:DL: renamed tmp file to file (/mnt/chip_counters.ini)
[1701099876.800030][82231:82231] CHIP:DL: NVS set: chip-counters/total-operational-hours = 0 (0x0)
[1701099876.800043][82231:82231] CHIP:DL: Inet Layer shutdown
[1701099876.800051][82231:82231] CHIP:DL: BLE shutdown
[1701099876.802640][82231:82231] CHIP:DL: System Layer shutdown
[1701099876.803121][82231:82231] CHIP:TOO: Run command failure: src/platform/Linux/bluez/ChipDeviceScanner.cpp:173: CHIP Error 0x00000032: Timeout

`interactive server` command listen failed

After installing chip-tool and connecting avahi-observe and bluez, I can successfully commissioning and controlling the matter device, but I can't run chip-tool as a background service.

The command I used was sudo chip-tool interactive server and I encountered the following error, the key error is listen failed with error 1.

However, the chip-tool I built using CHIP source code does not encounter any errors and starts normally, so I'm wondering if this is due to the snap program needing extra permissions or parameters?

For example, is it possible to not have permission to write to InteractiveCommands.cpp causing a runtime failure? If so, I wonder if I need to add similar code inside snapcraft.yaml#L90?

The source code for this command is located in InteractiveCommands.cpp, the purpose of which is to start a websocket service and accept connections and command requests.

interactive_server.txt

Seccomp violation when pairing and controlling devices

There may be some permission issues, but they don't appear to affect functionality.

Here is the debug info from snappy-debug when trying to pair with chip-tool pairing ble-thread:

= AppArmor =
Time: 2023-07-19T11:2
Log: apparmor="DENIED" operation="capable" class="cap" profile="/snap/snapd/19457/usr/lib/snapd/snap-confine" pid=36414 comm="snap-confine" capability=12  capname="net_admin"
Capability: net_admin
Suggestions:
* adjust program to not require 'CAP_NET_ADMIN' (see 'man 7 capabilities')
* add one of 'bluetooth-control, firewall-control, netlink-audit, netlink-connector, network-control, qualcomm-ipc-router' to 'plugs'
* do nothing if using systemd utility (eg, timedatectl): https://forum.snapcraft.io/t/managing-time-date-and-timezone-in-ubuntu-core/408/44
* do nothing (https://launchpad.net/bugs/1465724)

= AppArmor =
Time: 2023-07-19T11:2
Log: apparmor="DENIED" operation="capable" class="cap" profile="/snap/snapd/19457/usr/lib/snapd/snap-confine" pid=36414 comm="snap-confine" capability=38  capname="perfmon"
Capability: perfmon
Suggestions:
* adjust program to not require 'CAP_PERFMON' (see 'man 7 capabilities')
* do nothing if program otherwise works properly

= Seccomp =
Time: 2023-07-19T11:2
Log: auid=1000 uid=0 gid=0 ses=4 subj=snap.chip-tool.chip-tool pid=36414 comm="gmain-matter" exe="/snap/chip-tool/19/bin/chip-tool" sig=0 arch=c000003e 314(sched_setattr) compat=0 ip=0x7fe5c1e50a3d code=0x50000
Syscall: sched_setattr
Suggestion:
* add 'process-control' to 'plugs'

During onoff toggle:

= AppArmor =
Time: 2023-07-25T13:1
Log: apparmor="DENIED" operation="capable" class="cap" profile="/snap/snapd/19457/usr/lib/snapd/snap-confine" pid=48260 comm="snap-confine" capability=12  capname="net_admin"
Capability: net_admin
Suggestions:
* adjust program to not require 'CAP_NET_ADMIN' (see 'man 7 capabilities')
* add one of 'bluetooth-control, firewall-control, netlink-audit, netlink-connector, network-control, qualcomm-ipc-router' to 'plugs'
* do nothing if using systemd utility (eg, timedatectl): https://forum.snapcraft.io/t/managing-time-date-and-timezone-in-ubuntu-core/408/44
* do nothing (https://launchpad.net/bugs/1465724)

= AppArmor =
Time: 2023-07-25T13:1
Log: apparmor="DENIED" operation="capable" class="cap" profile="/snap/snapd/19457/usr/lib/snapd/snap-confine" pid=48260 comm="snap-confine" capability=38  capname="perfmon"
Capability: perfmon
Suggestions:
* adjust program to not require 'CAP_PERFMON' (see 'man 7 capabilities')
* do nothing if program otherwise works properly

Chip Tool tests not using the snap built from the PR

The test action doesn’t pass the local snap’s path to the tests. As a result, the tests run against the Chip Tool downloaded from the store.

Original PR where this issue was overlooked: canonical/matter-snap-testing#2

Relevant code: https://github.com/canonical/matter-snap-testing/blob/0f3c7fc001768aa541f8543bef1045d056aff033/test/action.yml#L44-L73

Example workflow logs showing that the snap was installed from the store: https://github.com/canonical/chip-tool-snap/actions/runs/7540266663/job/20524800647#step:2:101

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

This repository currently has no open or pending branches.

Detected dependencies

github-actions
.github/workflows/build-and-test-snap.yml
  • actions/checkout v4
  • snapcore/action-build v1
  • actions/upload-artifact v4
  • actions/checkout v4
  • actions/download-artifact v4
  • actions/setup-go v5
  • actions/upload-artifact v4
  • actions/checkout v4
  • docker/setup-qemu-action v3
  • diddlesnaps/snapcraft-multiarch-action v1
  • actions/upload-artifact v4
.github/workflows/cla-check.yml
  • canonical/has-signed-canonical-cla v1

  • Check this box to trigger a request for Renovate to run again on this repository

Separate installation of node and ZAP into a standalone part

The following script could be moved to a new part called nodjs-zap:

# Install NodeJS and ZAP tool for arm builds
if [[ $SNAP_ARCH == "arm64" ]]; then
set -x
mkdir node_js
cd node_js
wget https://nodejs.org/dist/v12.22.12/node-v12.22.12-linux-x64.tar.xz
tar xfvJ node-v12.22.12-linux-x64.tar.xz
cp -rn node-v12.22.12-linux-x64/. /opt/node-v12.22.12-linux-x64/
rm -r node-v12.22.12-linux-x64
rm -rf /opt/node
rm -rf /usr/bin/node
rm -rf /usr/bin/npm
rm -rf /usr/bin/npx
ln -s /opt/node-v12.22.12-linux-x64 /opt/node
ln -s /opt/node/bin/* /usr/bin
cd ..
rm -rf node_js
ZAP_VERSION=v2023.05.22-nightly
mkdir -p /opt/zap-${ZAP_VERSION}
git clone https://github.com/project-chip/zap.git /opt/zap-${ZAP_VERSION}
cd /opt/zap-${ZAP_VERSION}
git checkout -b ${ZAP_VERSION}
npm cache clean --force
npm install -g npm@latest
npm ci
export ZAP_DEVELOPMENT_PATH=/opt/zap-${ZAP_VERSION}
fi

Missing zap-cli fails arm64 builds in v1.1.0.1

The arm64 build of v1.1.0.1 fails with the following error:

:: [32/595] ACTION //third_party/connectedhomeip/src/controller/data_model:data_model_zapgen_zap_pregen(//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc)
:: FAILED: gen/third_party/connectedhomeip/src/controller/data_model/zap_pregen/zap-generated/access.h gen/third_party/connectedhomeip/src/controller/data_model/zap_pregen/zap-generated/gen_config.h gen/third_party/connectedhomeip/src/controller/data_model/zap_pregen/zap-generated/endpoint_config.h gen/third_party/connectedhomeip/src/controller/data_model/zap_pregen/zap-generated/CHIPClientCallbacks.h gen/third_party/connectedhomeip/src/controller/data_model/zap_pregen/zap-generated/CHIPClusters.h gen/third_party/connectedhomeip/src/controller/data_model/zap_pregen/zap-generated/IMClusterCommandHandler.cpp
:: python ../examples/chip-tool/third_party/connectedhomeip/third_party/pigweed/repo/pw_build/py/pw_build/python_runner.py --gn-root ../examples/chip-tool/ --current-path ../examples/chip-tool/third_party/connectedhomeip/src/controller/data_model --default-toolchain=//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc --current-toolchain=//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc --capture-output --python-dep-list-files gen/third_party/connectedhomeip/src/controller/data_model/data_model_zapgen_zap_pregen_metadata_path_list.txt -- ../examples/chip-tool/third_party/connectedhomeip/scripts/tools/zap/generate.py --no-prettify-output --templates /build/chip-tool/parts/connectedhomeip/src/examples/chip-tool/third_party/connectedhomeip/src/app/zap-templates/app-templates.json --output-dir /build/chip-tool/parts/connectedhomeip/src/build-examples/gen/third_party/connectedhomeip/src/controller/data_model/zap_pregen/zap-generated --lock-file /build/chip-tool/parts/connectedhomeip/src/build-examples/zap_gen.lock --parallel /build/chip-tool/parts/connectedhomeip/src/examples/chip-tool/third_party/connectedhomeip/src/controller/data_model/controller-clusters.zap
:: Searching for zcl file from /build/chip-tool/parts/connectedhomeip/src/examples/chip-tool/third_party/connectedhomeip/src/controller/data_model/controller-clusters.zap
:: FAILED TO EXECUTE ZAP GENERATION: No such file or directory - "zap-cli"
:: ********************************************************************************
:: * You may need to install zap. Please ensure one of these applies:
:: * - `zap-cli` is in $PATH. Install from https://github.com/project-chip/zap/releases
:: *   see docs/guides/BUILDING.md for details
:: * - `zap-cli` is in $ZAP_INSTALL_PATH. Use this option if you
:: *   installed zap but do not want to update $PATH
:: * - Point $ZAP_DEVELOPMENT_PATH to your local copy of zap that you
:: *   develop on (to use a developer build of zap)
:: ********************************************************************************
:: [33/595] ACTION //third_party/connectedhomeip/src/platform/Linux/dbus/openthread:openthread_gen(//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc)
:: [34/595] ACTION //third_party/connectedhomeip/src/platform/Linux/dbus/wpa:wpa_gen(//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc)
:: [35/595] ACTION //third_party/connectedhomeip/src/platform/Linux/dbus/bluez:bluez_gen(//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc)
:: [36/595] ACTION //third_party/connectedhomeip/src/platform/Linux/dbus/wpa:wpa_gen(//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc)
:: [37/595] ACTION //third_party/connectedhomeip/src/controller/data_model:data_model_codegen_codegen(//third_party/connectedhomeip/build/toolchain/linux:linux_arm64_gcc)
:: ninja: build stopped: subcommand failed.

Full build log: https://launchpadlibrarian.net/672227508/buildlog_snap_ubuntu_jammy_arm64_b17b131db72a1069b5f5c3fa87d05d81_BUILDING.txt.gz

Add snap connection commands for Ubuntu Core

chip-tool-snap/README.md

Lines 18 to 26 in 00c7f0f

Connect the [`avahi-observe`](https://snapcraft.io/docs/avahi-observe-interface) interface to allow DNS-SD based discovery:
```bash
sudo snap connect chip-tool:avahi-observe
```
Connect the [`bluez`](https://snapcraft.io/docs/bluez-interface) interface for device discovery over Bluetooth Low Energy (BLE):
```bash
sudo snap connect chip-tool:bluez
```

The above commands throw errors and should be adjusted for Ubuntu Core OS:

$ sudo snap connect chip-tool:avahi-observe
error: snap "snapd" has no "avahi-observe" interface slots
$ sudo snap connect chip-tool:bluez
error: snap "snapd" has no "bluez" interface slots
$ sudo snap connect chip-tool:avahi-observe avahi
$ sudo snap connect chip-tool:bluez bluez:service

Mark `readLogFile` as a test helper function

This could be marked as a helper function:

func readLogFile(t *testing.T, filePath string) (string, error) {
    t.Helper()
    text, err := os.ReadFile(filePath)
    if err != nil {
        return "", err
    }
    return string(text), nil
}

(then change the in the call of the function also to: logs, err := readLogFile(t, appLogPath) )

Originally posted by @locnnil in #36 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.