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 #287

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions .github/workflows/snap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Snap Testing

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# allow manual trigger
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build and upload snap
id: build
uses: canonical/edgex-snap-testing/build@v2
outputs:
snap: ${{steps.build.outputs.snap}}

test:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download and test snap
uses: canonical/edgex-snap-testing/test@v2
with:
name: device-virtual


9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,12 @@ internal/driver/db/
cmd/device-virtual
cmd/db/
VERSION

# snap files
*.snap
*.assert
prime/
stage/
parts/
squashfs-root/

38 changes: 38 additions & 0 deletions snap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# EdgeX Device Virtual Service Snap
[![edgex-device-virtual](https://snapcraft.io/edgex-device-virtual/badge.svg)](https://snapcraft.io/edgex-device-virtual)

This directory contains the snap packaging of the EdgeX Device Virtual device service.

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

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

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

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. Note that the **auto connection does NOT happen right** now because the snap publisher isn't same as the `edgexfoundry` platrform snap (i.e. Canonical).

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-virtual` command.

To manually connect and obtain a token:
```bash
sudo snap connect edgexfoundry:edgex-secretstore-token edgex-device-virtual:edgex-secretstore-token
```

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

[edgex-device-virtual]: https://snapcraft.io/edgex-device-virtual
[docs]: https://docs.edgexfoundry.org/2.2/getting-started/Ch-GettingStartedSnapUsers/#device-virtual
[secret-store-token]: https://docs.edgexfoundry.org/2.2/getting-started/Ch-GettingStartedSnapUsers/#secret-store-token

18 changes: 18 additions & 0 deletions snap/local/hooks/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
GO=go
HOOKS=cmd/configure/configure cmd/install/install
GOFLAGS=-ldflags="-s -w"

build: $(HOOKS)

cmd/configure/configure:
$(GO) build $(GOFLAGS) -o $@ ./cmd/configure

cmd/install/install:
$(GO) build $(GOFLAGS) -o $@ ./cmd/install

tidy:
go mod tidy -compat=1.17

clean:
rm -f $(HOOKS)

74 changes: 74 additions & 0 deletions snap/local/hooks/cmd/configure/configure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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"
"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 main() {
log.SetComponentName("configure")

log.Info("Enabling config options")
err := snapctl.Set("app-options", "true").Run()
if err != nil {
log.Errorf("could not enable config options: %v", err)
os.Exit(1)
}
MonicaisHer marked this conversation as resolved.
Show resolved Hide resolved

log.Info("Processing options")
err = options.ProcessAppConfig("device-virtual")
if err != nil {
log.Errorf("could not process options: %v", err)
os.Exit(1)
}

// 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.Errorf("Reading config 'autostart' failed: %v", err)
os.Exit(1)
}
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("device-virtual").Enable().Run()
if err != nil {
log.Errorf("Can't start service: %s", err)
os.Exit(1)
}
case "false", "no":
// no action necessary
default:
log.Errorf("Invalid value for 'autostart': %s", autostart)
os.Exit(1)
}
}
105 changes: 105 additions & 0 deletions snap/local/hooks/cmd/install/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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-virtual/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
}

return nil
}

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

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

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

return nil
}

func installDevProfiles() error {
profs := [...]string{"binary", "bool", "float", "int", "uint"}
profilesDir := "/config/device-virtual/res/profiles/"

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

for _, v := range profs {
err = hooks.CopyFile(
hooks.Snap+profilesDir+"device.virtual."+v+".yaml",
hooks.SnapData+profilesDir+"device.virtual."+v+".yaml")
if err != nil {
return err
}
}

return nil
}

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

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

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

err = installDevProfiles()
if err != nil {
log.Errorf("error installing device profiles config: %s", err)
os.Exit(1)
}
}
6 changes: 6 additions & 0 deletions snap/local/hooks/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module github.com/edgexfoundry/device-virtual-go/hooks

go 1.17

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

13 changes: 13 additions & 0 deletions snap/local/hooks/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
github.com/canonical/edgex-snap-hooks/v2 v2.2.0 h1:4pDnikrtyrxiynTM49+ppH7hXBx5C7dWUOjEEisCXmI=
github.com/canonical/edgex-snap-hooks/v2 v2.2.0/go.mod h1:rOxrwdYL7hJDhxFH3uV+nVgLPjWOhJWgM5PRD5YG1jI=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

19 changes: 19 additions & 0 deletions snap/local/runtime-helpers/bin/startup-env-var.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash -e

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

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

# binary name == service name/key
SERVICE=$(basename "$BINPATH")
SERVICE_ENV="$SNAP_DATA/config/$SERVICE/res/$SERVICE.env"

if [ -f "$SERVICE_ENV" ]; then
logger "edgex service override: : sourcing $SERVICE_ENV"
source "$SERVICE_ENV"
fi

exec "$@"

Loading