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

feat(snap): Add snap packaging #30

Merged
merged 29 commits into from
Jul 7, 2022
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fbae2df
feat(snap): initial packaging
farshidtz May 18, 2022
862b54a
feat(snap): fix installation and runtime issues
farshidtz May 19, 2022
a30f13e
feat(snap): add interfaces for confinement
farshidtz May 19, 2022
e81ae1c
fix(snap): move header file to runtime-helpers
farshidtz May 19, 2022
f6542a3
fix(snap): add rtsp to auto start, strip binaries
farshidtz May 20, 2022
bdfb580
fix: correct location for header file, refactor
farshidtz May 20, 2022
b80c245
docs(snap): clarify auto connection
farshidtz May 20, 2022
36ec5bb
docs: add general usb camera example
farshidtz May 20, 2022
13faad9
Merge remote-tracking branch 'upstream/main' into snap
farshidtz May 20, 2022
21b1265
style: add newlines
farshidtz May 23, 2022
81273f7
docs(snap): improve addon service instructions
farshidtz May 23, 2022
330d9cc
docs(snap): improve camera interface instrcutionns
farshidtz May 23, 2022
554a70a
docs(snap): add comments to libpulse
farshidtz May 23, 2022
c4eb13c
docs(snap): move development details to docs and PR description
farshidtz May 24, 2022
a19e9f5
fix(snap): append libpulse to library paths
farshidtz May 24, 2022
cf5febe
docs: Revert "docs: add general usb camera example"
farshidtz May 25, 2022
dd2391e
feat: switch to core22
farshidtz May 25, 2022
bc793f9
fix: install example device config
farshidtz May 27, 2022
e9b21ae
Merge remote-tracking branch 'upstream/main' into snap
farshidtz May 27, 2022
1f03470
docs: package rtsp-simple-server's licence
farshidtz May 27, 2022
97d9f59
docs: add comment to explain the copy workaround
farshidtz May 27, 2022
4df80ee
fix: add missing curl build dependency
farshidtz May 27, 2022
4eccf07
fix: Add scripts to call compiled hooks
farshidtz Jun 28, 2022
1eaa599
refactor: upgrade to edgex-snap-hooks and local snap refactoring
farshidtz Jun 29, 2022
91b64af
build: go mod tidy
farshidtz Jun 30, 2022
47482b0
test(snap): Add Github workflow for snap testing
farshidtz Jun 30, 2022
ad82447
fix: write VERSION file to stage directory instead of to source
farshidtz Jun 30, 2022
52d4126
test: switch to v2 of build/test actions
farshidtz Jun 30, 2022
4c4ab6a
docs: remove license field
farshidtz Jul 5, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,12 @@ LintOutput.json
device-usb-camera
run

#VERSION
VERSION

# snap files
*.snap
*.assert
prime/
stage/
parts/
squashfs-root/
45 changes: 45 additions & 0 deletions snap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# EdgeX USB Camera Device Service Snap
[![edgex-device-usb-camera](https://snapcraft.io/edgex-device-usb-camera/badge.svg)](https://snapcraft.io/edgex-device-usb-camera)

This directory contains the snap packaging of the EdgeX USB Camera device service.

The snap is built automatically and published on the Snap Store as [edgex-device-usb-camera].

For usage instructions, please refer to Device Camera section in [Getting Started using Snaps][docs].

## Build from source
Execute the following command from the top-level directory of this repo:
```
snapcraft -v
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should mention that building this snap remains "challenging" and at least offer some options. I don't think the given option "just works".

Copy link
Member Author

@farshidtz farshidtz Jul 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As explained in another comment, we have been able to build it without problems locally and on CI servers. If there are any OS-specific challenges related to using snapcraft to build core22-based snaps, it should be raised on snapcraft issue trackers.

This will create a snap package file with `.snap` extension. It can be installed locally by setting the `--dangerous` flag:
```bash
sudo snap install --dangerous <snap-file>
```

The [snapcraft overview](https://snapcraft.io/docs/snapcraft-overview) provides additional details.

### Obtain a Secret Store token
The `edgex-secretstore-token` snap slot makes it possible to automatically receive a token from a locally installed platform snap.

If the snap is built and installed locally, the interface will not auto-connect. You can check the status of the connections by running the `snap connections edgex-device-usb-camera` command.

To manually connect and obtain a token:
farshidtz marked this conversation as resolved.
Show resolved Hide resolved
```bash
sudo snap connect edgexfoundry:edgex-secretstore-token edgex-device-usb-camera:edgex-secretstore-token
```

Please refer [here][secret-store-token] for further information.

### Connect the camera interface
The [`camera`](https://snapcraft.io/docs/camera-interface) interface is currently **NOT automatically connected** as it is pending auto-connection permissions from the store.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we requested these permissions yet?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet. We will do so once we have a stable source and build that can be reviewed by the store.


To connect manually:
```
snap connect edgex-device-usb-camera:camera :camera
```

[edgex-device-usb-camera]: https://snapcraft.io/edgex-device-usb-camera
[docs]: https://docs.edgexfoundry.org/2.2/getting-started/Ch-GettingStartedSnapUsers/#device-usb-camera
[secret-store-token]: https://docs.edgexfoundry.org/2.2/getting-started/Ch-GettingStartedSnapUsers/#secret-store-token
3 changes: 3 additions & 0 deletions snap/hooks/configure
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a workaround for snapcraft 7, correct? Did you ever get a response from the snapcraft team on this? At minimum, we should probably add a note to this script noting that it's a workaround.

Copy link
Member Author

@farshidtz farshidtz Jul 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in this comment, I've reported the bug.

We are no longer affected by it because we have refactored the hooks to have a single binary executable. This reduces the build complexity (code, time) and snap size. The same improvement is being rolled out to other snaps.

exec $SNAP/bin/helper-go configure
3 changes: 3 additions & 0 deletions snap/hooks/install
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash -e

exec $SNAP/bin/helper-go install
farshidtz marked this conversation as resolved.
Show resolved Hide resolved
21 changes: 21 additions & 0 deletions snap/local/bin/source-env-file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash -e

# convert cmdline to string array
ARGV=($@)

# grab binary path
BINPATH="${ARGV[0]}"

# binary name == service name/key
SERVICE=$(basename "$BINPATH")
ENV_FILE="$SNAP_DATA/config/$SERVICE/res/$SERVICE.env"
TAG="edgex-$SERVICE."$(basename "$0")

if [ -f "$ENV_FILE" ]; then
logger --tag=$TAG "sourcing $ENV_FILE"
set -o allexport
source "$ENV_FILE" set
set +o allexport
fi

exec "$@"
8 changes: 8 additions & 0 deletions snap/local/helper-go/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
build:
go build -ldflags="-s -w" -o helper-go

tidy:
go mod tidy -compat=1.17

clean:
rm -f helper-go
67 changes: 67 additions & 0 deletions snap/local/helper-go/configure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2022 Canonical Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
* SPDX-License-Identifier: Apache-2.0'
*/

package main

import (
"strings"

"github.com/canonical/edgex-snap-hooks/v2/log"
"github.com/canonical/edgex-snap-hooks/v2/options"
"github.com/canonical/edgex-snap-hooks/v2/snapctl"
)

func configure() {
log.SetComponentName("configure")

// config options are always enabled for this service
err := snapctl.Set("app-options", "true").Run()
if err != nil {
log.Fatalf("could not enable config options: %v", err)
}

err = options.ProcessAppConfig("device-usb-camera")
if err != nil {
log.Fatalf("could not process options: %v", err)
}

// If autostart is not explicitly set, default to "no"
// as only example service configuration and profiles
// are provided by default.
autostart, err := snapctl.Get("autostart").Run()
if err != nil {
log.Fatalf("Reading config 'autostart' failed: %v", err)
}
if autostart == "" {
log.Debug("autostart is NOT set, initializing to 'no'")
autostart = "no"
}
autostart = strings.ToLower(autostart)
log.Debugf("autostart=%s", autostart)

// services are stopped/disabled by default in the install hook
switch autostart {
case "true", "yes":
err = snapctl.Start("rtsp-simple-server", "device-usb-camera").Enable().Run()
if err != nil {
log.Fatalf("Can't start service: %s", err)
}
case "false", "no":
// no action necessary
default:
log.Fatalf("Invalid value for 'autostart': %s", autostart)
}
}
11 changes: 11 additions & 0 deletions snap/local/helper-go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/edgexfoundry/device-camera-go/hooks

require github.com/canonical/edgex-snap-hooks/v2 v2.3.0

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/stretchr/testify v1.7.1 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

go 1.17
15 changes: 15 additions & 0 deletions snap/local/helper-go/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
github.com/canonical/edgex-snap-hooks/v2 v2.3.0 h1:ddXo8b5AsYjTiZ1APyeHWri0//KfU5qhDwPkyK0TUTc=
github.com/canonical/edgex-snap-hooks/v2 v2.3.0/go.mod h1:rOxrwdYL7hJDhxFH3uV+nVgLPjWOhJWgM5PRD5YG1jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
107 changes: 107 additions & 0 deletions snap/local/helper-go/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (C) 2022 Canonical Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
* SPDX-License-Identifier: Apache-2.0'
*/

package main

import (
"os"

hooks "github.com/canonical/edgex-snap-hooks/v2"
"github.com/canonical/edgex-snap-hooks/v2/env"
"github.com/canonical/edgex-snap-hooks/v2/log"
)

// installProfiles copies the profile configuration.toml files from $SNAP to $SNAP_DATA.
func installConfig() error {
resPath := "/config/device-usb-camera/res"
err := os.MkdirAll(env.SnapData+resPath, 0755)
if err != nil {
return err
}

path := resPath + "/configuration.toml"
err = hooks.CopyFile(
env.Snap+path,
env.SnapData+path)
if err != nil {
return err
}

path = "/config/rtsp-simple-server.yml"
err = hooks.CopyFile(
env.Snap+path,
env.SnapData+path)
if err != nil {
return err
}

return nil
}

func installDevices() error {
devicesDir := "/config/device-usb-camera/res/devices"

err := os.MkdirAll(env.SnapData+devicesDir, 0755)
if err != nil {
return err
}

err = hooks.CopyFile(
hooks.Snap+devicesDir+"/general.usb.camera.toml.example",
hooks.SnapData+devicesDir+"/general.usb.camera.toml.example")
if err != nil {
return err
}

return nil
}

func installDevProfiles() error {
profilesDir := "/config/device-usb-camera/res/profiles"

err := os.MkdirAll(env.SnapData+profilesDir, 0755)
if err != nil {
return err
}

err = hooks.CopyFile(
hooks.Snap+profilesDir+"/general.usb.camera.yaml",
hooks.SnapData+profilesDir+"/general.usb.camera.yaml")
if err != nil {
return err
}

return nil
}

func install() {
log.SetComponentName("install")

err := installConfig()
if err != nil {
log.Fatalf("error installing config file: %s", err)
}

err = installDevices()
if err != nil {
log.Fatalf("error installing devices config: %s", err)
}

err = installDevProfiles()
if err != nil {
log.Fatalf("error installing device profiles config: %s", err)
}
}
32 changes: 32 additions & 0 deletions snap/local/helper-go/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2022 Canonical Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
* SPDX-License-Identifier: Apache-2.0'
*/

package main

import (
"os"
)

func main() {
subCommand := os.Args[1]
switch subCommand {
case "install":
install()
case "configure":
configure()
default:
panic("Unknown subcommand: " + subCommand)
}
}
Loading