Skip to content

Commit

Permalink
feat: Back port service template from hanoi branch
Browse files Browse the repository at this point in the history
Top level `test` target builds and tests the new template

close #674

Signed-off-by: lenny <[email protected]>
  • Loading branch information
lenny committed Feb 17, 2021
1 parent 46ccba1 commit 324c3d5
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 86 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ GO=CGO_ENABLED=1 GO111MODULE=on go
build:
make -C ./app-service-template build

test:
test-template:
make -C ./app-service-template test

test: build test-template
$(GO) test ./... -coverprofile=coverage.out ./...
$(GO) vet ./...
gofmt -l .
Expand Down
2 changes: 1 addition & 1 deletion app-service-template/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ docker-compose*
*/bin
*/obj
README.md
.vscode
.vscode
2 changes: 1 addition & 1 deletion app-service-template/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ go.sum
coverage.out
logs/
.idea
VERSION
VERSION
14 changes: 7 additions & 7 deletions app-service-template/Attribution.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@ https://github.com/cenkalti/backoff/blob/master/LICENSE
eclipse/paho.mqtt.golang (Eclipse Public License 1.0) https://github.com/eclipse/paho.mqtt.golang
https://github.com/eclipse/paho.mqtt.golang/blob/master/LICENSE

edgexfoundry/app-functions-sdk-go (Apache 2.0) https://github.com/edgexfoundry/app-functions-sdk-go
edgexfoundry/app-functions-sdk-go (Apache 2.0) https://github.com/edgexfoundry/app-functions-sdk-go/v2
https://github.com/edgexfoundry/app-functions-sdk-go/blob/master/LICENSE

edgexfoundry/go-mod-core-contracts (Apache 2.0) https://github.com/edgexfoundry/go-mod-core-contracts
edgexfoundry/go-mod-core-contracts (Apache 2.0) https://github.com/edgexfoundry/go-mod-core-contracts/v2
https://github.com/edgexfoundry/go-mod-core-contracts/blob/master/LICENSE

edgexfoundry/go-mod-registry (Apache 2.0) https://github.com/edgexfoundry/go-mod-registry
edgexfoundry/go-mod-registry (Apache 2.0) https://github.com/edgexfoundry/go-mod-registry/v2
https://github.com/edgexfoundry/go-mod-registry/blob/master/LICENSE

edgexfoundry/go-mod-messaging (Apache 2.0) https://github.com/edgexfoundry/go-mod-messaging
edgexfoundry/go-mod-messaging (Apache 2.0) https://github.com/edgexfoundry/go-mod-messaging/v2
https://github.com/edgexfoundry/go-mod-messaging/blob/master/LICENSE

edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-secrets
edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-secrets/v2
https://github.com/edgexfoundry/go-mod-secrets/blob/master/LICENSE

edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-bootstrap
edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-bootstrap/v2
https://github.com/edgexfoundry/go-mod-bootstrap/blob/master/LICENSE

edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-configuration
edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-configuration/v2
https://github.com/edgexfoundry/go-mod-configuration/blob/master/LICENSE

BurntSushi/toml (MIT) https://github.com/BurntSushi/toml
Expand Down
2 changes: 2 additions & 0 deletions app-service-template/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ GO=CGO_ENABLED=1 go

# VERSION file is not needed for local development, In the CI/CD pipeline, a temporary VERSION file is written
# if you need a specific version, just override below
# TODO: If your service is not being upstreamed to Edgex Foundry, you need to determine the best approach for
# setting your service's version for non-development builds.
APPVERSION=$(shell cat ./VERSION 2>/dev/null || echo 0.0.0)

# This pulls the version of the SDK from the go.mod file. If the SDK is the only required module,
Expand Down
14 changes: 7 additions & 7 deletions app-service-template/README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
# Application Service Template

The contents of this folder is a buildable/runnable template for a new custom application service based on the Hanoi 1.3.1 release of the App Functions SDK.
This folder contains a buildable/runnable template for a new custom application service based on the Hanoi 1.3.1 release of the App Functions SDK.

> **Note**: If you only need to use the built-in pipeline functions, then it is advisable that you use `App Service Configurable` rather then create a new custom application service. See [here](https://docs.edgexfoundry.org/1.3/microservices/application/AppServiceConfigurable/) for more details on `App Service Configurable`
Do the following to use this template to create your new custom application service:
Follow the instructions below to create your new customer application service:

1. Copy contents of this folder to your new folder

2. Change name `new-app-service` in go.mod to an appropriate Go Module name for your service.
2. Change name `new-app-service` in go.mod to an appropriate Go Module name for your service

- Typically this is the URL to the repository for your service

3. Do a global search and replace on `new-app-service` to replace it with the name of your service

- Note that this name is used as the service key so it needs to use dashes rather than spaces in the name
- Note that this name is used as the service key, so it needs to use dashes rather than spaces in the name and avoid other special characters

4. Adjust your local import statements to match the name you selected in the go.mod file

- Only needed in `main.go` if Go Module name changed to a URL
- Only needed in `main.go` if the Go Module name changed to a URL

5. Run unit tests to verify changes didn't break the code

- `make test`

6. Build executable to verify the binary still builds
6. Verify you are able to build the executable

- `make build`

7. Update the `makefile` docker build to adjust image name appropriately

8. Build docker image to verify the docker image still builds with your image name
8. Verify the docker image still builds with your new image name

- `make docker`

Expand Down
51 changes: 25 additions & 26 deletions app-service-template/functions/sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ import (
"fmt"
"strings"

"github.com/edgexfoundry/app-functions-sdk-go/appcontext"
"github.com/edgexfoundry/go-mod-core-contracts/models"
"github.com/edgexfoundry/app-functions-sdk-go/v2/appcontext"
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2"
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos"
)

// TODO: Change this Sample to be your custom type and function(s)
// TODO: Create your custom type and function(s) and remove these samples

// TODO: Add parameters that the function(s) will need each time one is executed
func NewSample() Sample {
Expand All @@ -46,35 +47,33 @@ func (s *Sample) LogEventDetails(edgexcontext *appcontext.Context, params ...int
return false, errors.New("no Event Received")
}

event, ok := params[0].(models.Event)
event, ok := params[0].(dtos.Event)
if !ok {
return false, errors.New("type received is not an Event")
}

edgexcontext.LoggingClient.Info(
fmt.Sprintf("Event recieved: ID=%s, Device=%s, and ReadingCount=%d",
event.ID,
event.Device,
len(event.Readings)))
edgexcontext.LoggingClient.Infof("Event received: ID=%s, Device=%s, and ReadingCount=%d",
event.Id,
event.DeviceName,
len(event.Readings))
for index, reading := range event.Readings {
switch strings.ToLower(reading.ValueType) {
case strings.ToLower(models.ValueTypeBinary):
edgexcontext.LoggingClient.Info(
fmt.Sprintf("Reading #%d received with ID=%s, Resource=%s, ValueType=%s, MediaType=%s and BinaryValue of size=`%d`",
index+1,
reading.Id,
reading.Name,
reading.ValueType,
reading.MediaType,
len(reading.BinaryValue)))
case strings.ToLower(v2.ValueTypeBinary):
edgexcontext.LoggingClient.Infof(
"Reading #%d received with ID=%s, Resource=%s, ValueType=%s, MediaType=%s and BinaryValue of size=`%d`",
index+1,
reading.Id,
reading.ResourceName,
reading.ValueType,
reading.MediaType,
len(reading.BinaryValue))
default:
edgexcontext.LoggingClient.Info(
fmt.Sprintf("Reading #%d received with ID=%s, Resource=%s, ValueType=%s, Value=`%s`",
index+1,
reading.Id,
reading.Name,
reading.ValueType,
reading.Value))
edgexcontext.LoggingClient.Infof("Reading #%d received with ID=%s, Resource=%s, ValueType=%s, Value=`%s`",
index+1,
reading.Id,
reading.ResourceName,
reading.ValueType,
reading.Value)
}
}

Expand All @@ -91,7 +90,7 @@ func (s *Sample) ConvertEventToXML(edgexcontext *appcontext.Context, params ...i
return false, errors.New("no Event Received")
}

event, ok := params[0].(models.Event)
event, ok := params[0].(dtos.Event)
if !ok {
return false, errors.New("type received is not an Event")
}
Expand Down
47 changes: 19 additions & 28 deletions app-service-template/functions/sample_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ package functions

import (
"testing"
"time"

"github.com/edgexfoundry/app-functions-sdk-go/appcontext"
"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
"github.com/edgexfoundry/go-mod-core-contracts/models"
"github.com/edgexfoundry/app-functions-sdk-go/v2/appcontext"
"github.com/edgexfoundry/go-mod-core-contracts/v2/clients/logger"
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2"
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos"
"github.com/stretchr/testify/require"

"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)

// This file contains example of how to unit test pipeline functions
// TODO: Change these sample unit tests to test your custom type and function(s)

var TestEventId = uuid.New().String()

func TestSample_LogEventDetails(t *testing.T) {
expectedEvent := createTestEvent()
expectedEvent := createTestEvent(t)
expectedContinuePipeline := true

target := NewSample()
Expand All @@ -44,7 +44,7 @@ func TestSample_LogEventDetails(t *testing.T) {
}

func TestSample_ConvertEventToXML(t *testing.T) {
event := createTestEvent()
event := createTestEvent(t)
expectedXml, _ := event.ToXML()
expectedContinuePipeline := true

Expand All @@ -57,7 +57,8 @@ func TestSample_ConvertEventToXML(t *testing.T) {
}

func TestSample_OutputXML(t *testing.T) {
expectedXml, _ := createTestEvent().ToXML()
testEvent := createTestEvent(t)
expectedXml, _ := testEvent.ToXML()
expectedContinuePipeline := false
appContext := creatTestAppSdkContext()

Expand All @@ -68,36 +69,26 @@ func TestSample_OutputXML(t *testing.T) {
assert.Equal(t, expectedContinuePipeline, actualContinuePipeline)
assert.Nil(t, result)
assert.Equal(t, expectedXml, actualXml)

}

func createTestEvent() models.Event {
func createTestEvent(t *testing.T) dtos.Event {
deviceName := "MyDevice"
profileName := "MyProfile"
resourceName := "MyResource"

event := models.Event{
ID: TestEventId,
Device: deviceName,
Origin: time.Now().UnixNano(),
Tags: make(map[string]string),
}

event.Readings = append(event.Readings, models.Reading{
Id: uuid.New().String(),
Origin: time.Now().UnixNano(),
Device: deviceName,
Name: "MyReading",
Value: "1234",
ValueType: models.ValueTypeInt32,
})
event := dtos.NewEvent(profileName, deviceName)
err := event.AddSimpleReading(resourceName, v2.ValueTypeInt32, int32(1234))
require.NoError(t, err)

event.Tags["WhereAmI"] = "NotKansas"
event.Tags = map[string]string{
"WhereAmI": "NotKansas",
}

return event
}

func creatTestAppSdkContext() *appcontext.Context {
return &appcontext.Context{
EventID: TestEventId,
CorrelationID: uuid.New().String(),
LoggingClient: logger.NewMockClient(),
}
Expand Down
12 changes: 8 additions & 4 deletions app-service-template/go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// TODO: Update the Attrbuition.txt file when adding/removing dependencies

module new-app-service

go 1.15

require (
github.com/edgexfoundry/app-functions-sdk-go v1.3.1
github.com/edgexfoundry/go-mod-core-contracts v0.1.112
github.com/google/uuid v1.1.2
github.com/stretchr/testify v1.6.1
github.com/edgexfoundry/app-functions-sdk-go/v2 v2.0.0-dev.14
github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0-dev.23
github.com/google/uuid v1.2.0
github.com/stretchr/testify v1.7.0
)

replace github.com/edgexfoundry/app-functions-sdk-go/v2 => ../../app-functions-sdk-go
19 changes: 11 additions & 8 deletions app-service-template/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
package main

import (
"fmt"
"os"

"github.com/edgexfoundry/app-functions-sdk-go/appsdk"
"github.com/edgexfoundry/app-functions-sdk-go/pkg/transforms"
"github.com/edgexfoundry/app-functions-sdk-go/v2/appsdk"
"github.com/edgexfoundry/app-functions-sdk-go/v2/pkg/transforms"

"new-app-service/functions"
)
Expand All @@ -37,28 +36,32 @@ func main() {

edgexSdk := &appsdk.AppFunctionsSDK{ServiceKey: serviceKey}
if err := edgexSdk.Initialize(); err != nil {
edgexSdk.LoggingClient.Error(fmt.Sprintf("SDK initialization failed: %s\n", err.Error()))
edgexSdk.LoggingClient.Errorf("SDK initialization failed: %s", err.Error())
os.Exit(-1)
}

// TODO: Replace with retrieving your custom ApplicationSettings from configuration
deviceNames, err := edgexSdk.GetAppSettingStrings("DeviceNames")
if err != nil {
edgexSdk.LoggingClient.Error("failed to retrieve DeviceNames from configuration: %s\n", err.Error())
edgexSdk.LoggingClient.Errorf("failed to retrieve DeviceNames from configuration: %s", err.Error())
os.Exit(-1)
}

// TODO: Replace below functions with built in and/or your custom functions for your use case.
// See https://docs.edgexfoundry.org/1.3/microservices/application/BuiltIn/ for list of built-in functions
sample := functions.NewSample()
edgexSdk.SetFunctionsPipeline(
transforms.NewFilter(deviceNames).FilterByDeviceName,
err = edgexSdk.SetFunctionsPipeline(
transforms.NewFilterFor(deviceNames).FilterByDeviceName,
sample.LogEventDetails,
sample.ConvertEventToXML,
sample.OutputXML)
if err != nil {
edgexSdk.LoggingClient.Errorf("SetFunctionsPipeline returned error: %s", err.Error())
os.Exit(-1)
}

if err := edgexSdk.MakeItRun(); err != nil {
edgexSdk.LoggingClient.Error(fmt.Sprintf("MakeItRun returned error: %s", err.Error()))
edgexSdk.LoggingClient.Errorf("MakeItRun returned error: %s", err.Error())
os.Exit(-1)
}

Expand Down
7 changes: 4 additions & 3 deletions app-service-template/res/configuration.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ BootTimeout = '30s'
ClientMonitor = '15s'
CheckInterval = '10s'
Host = 'localhost'
Port = 49600 # TODO: set this port appropriatly
Port = 49600 # TODO: set this port appropriately
Protocol = 'http'
ReadMaxLimit = 100
StartupMsg = 'new-app-service Application Service has started'
Expand Down Expand Up @@ -63,7 +63,7 @@ RetryWaitPeriod = "1s"

[Binding]
Type="edgex-messagebus"
SubscribeTopic="events"
SubscribeTopics="events, edgex/events"
PublishTopic="event-xml" #TODO: remove if service is NOT publishing back to the message bus

[MessageBus]
Expand All @@ -81,7 +81,7 @@ Type = 'zero'
# Otherwise remove this commentedout block
#[Binding]
#Type="edgex-messagebus"
#SubscribeTopics="events"
#SubscribeTopics="events, edgex/events/#"
#PublishTopic="event-xml" # TODO: Remove if service is NOT publishing back to the message bus
#
#[MessageBus]
Expand All @@ -98,5 +98,6 @@ Type = 'zero'
[ApplicationSettings]
# TODO: Add custom settings needed by your app service
# This can be any Key/Value pair you need.
# For more details see: https://docs.edgexfoundry.org/1.3/microservices/application/GeneralAppServiceConfig/#application-settings
# Example that works with devices from the Virtual Device service:
DeviceNames = "Random-Boolean-Device, Random-Integer-Device, Random-UnsignedInteger-Device, Random-Float-Device, Random-Binary-Device"

0 comments on commit 324c3d5

Please sign in to comment.