--- /dev/null
+package servicemgr
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "log"
+ "net"
+ "os/exec"
+ "strconv"
+ "strings"
+)
+
+// ExecuteApp function
+func ExecuteApp(target string, name string, args []string, notiChan chan string) (serviceID uint64, err error) {
+ appInfo := make(map[string]interface{})
+
+ serviceID = createServiceMap(name, notiChan)
+ appInfo[ConstKeyServiceID] = serviceID
+
+ if args != nil {
+ appInfo[ConstKeyUserArgs] = args
+ }
+ appInfo[ConstKeyServiceName] = name
+
+ if strings.Compare(target, getOutboundIP()) == 0 {
+ appInfo[ConstKeyNotiTargetURL] = ConstLocalTarget
+ err = executeLocalEnv(appInfo)
+ } else {
+ appInfo[ConstKeyNotiTargetURL] = ConstPrefixHTTP + target + ":" + strconv.Itoa(ConstWellknownPort)
+ err = executeRemoteEnv(appInfo, target)
+ }
+
+ return
+}
+
+// Run is trigger point executing binary
+func Run(distService map[string]interface{}) {
+ var serviceID uint64
+
+ switch distService[ConstKeyServiceID].(type) {
+ case uint64:
+ serviceID = distService[ConstKeyServiceID].(uint64)
+ case float64:
+ serviceID = uint64(distService[ConstKeyServiceID].(float64))
+ }
+
+ serviceName := distService[ConstKeyServiceName].(string)
+
+ var args []string
+ userArgs := distService[ConstKeyUserArgs]
+
+ if userArgs != nil {
+ switch userArgs.(type) {
+ case []string:
+ for _, param := range userArgs.([]string) {
+ args = append(args, param)
+ }
+ case []interface{}:
+ args = make([]string, len(userArgs.([]interface{})))
+ for _, param := range userArgs.([]interface{}) {
+ args = append(args, fmt.Sprint(param))
+ }
+ }
+ } else {
+ args = nil
+ }
+ notificationTargetURL := distService[ConstKeyNotiTargetURL].(string)
+
+ service := Service{serviceID, serviceName, args, notificationTargetURL}
+
+ service.execute()
+}
+
+// HandleNoti is for handling notificiation from servie
+func HandleNoti(statusNoti map[string]interface{}) (err error) {
+ var serviceID uint64
+ switch statusNoti[ConstKeyServiceID].(type) {
+ case uint64:
+ serviceID = statusNoti[ConstKeyServiceID].(uint64)
+ case float64:
+ serviceID = uint64(statusNoti[ConstKeyServiceID].(float64))
+ }
+
+ notiChan, _ := getNotiChan(serviceID)
+
+ if notiChan == nil {
+ return
+ }
+
+ notiChan <- statusNoti[ConstKeyStatus].(string)
+ ServiceMap.Remove(serviceID)
+
+ return
+}
+
+func checkError(err error) bool {
+ if err != nil {
+ log.Println(err.Error())
+ return true
+ }
+ return false
+}
+
+func getOutboundIP() string {
+ conn, err := net.Dial("udp", "8.8.8.8:80")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer conn.Close()
+
+ localAddr := conn.LocalAddr().(*net.UDPAddr)
+
+ return localAddr.IP.String()
+}
+
+func executeLocalEnv(appInfo map[string]interface{}) (err error) {
+ // check execution validation
+ _, err = exec.LookPath(appInfo[ConstKeyServiceName].(string))
+
+ if checkError(err) == false {
+ go Run(appInfo)
+ }
+
+ return
+}
+
+func executeRemoteEnv(appInfo map[string]interface{}, target string) (err error) {
+ reqBytes, _ := json.Marshal(appInfo)
+ executeTarget := target + ":" + strconv.Itoa(ConstWellknownPort) + ConstServiceExecuteURI
+
+ str, err := sendPostJSONMsg(executeTarget, reqBytes)
+
+ if err == nil {
+ if str == ConstServiceStatusFailed {
+ err = errors.New("Failed")
+ }
+ }
+
+ return
+}
--- /dev/null
+package servicemgr
+
+import (
+ "strings"
+ "testing"
+ "time"
+)
+
+var (
+ // targetRemoteDeviceAddr = "10.113.175.144"
+ targetLocalAddr = getOutboundIP()
+ serviceID uint64
+)
+
+const (
+ serviceName = "ls"
+ serviceName2 = "main2"
+)
+
+func init() {
+ InitServiceMap()
+}
+
+func retError(t *testing.T, err error) {
+ t.Helper()
+
+ if err != nil {
+ t.Error(err.Error())
+ }
+}
+
+func TestExecuteApp(t *testing.T) {
+ notiChan := make(chan string)
+
+ _, err := ExecuteApp(targetLocalAddr, serviceName, nil, notiChan)
+ retError(t, err)
+
+ time.Sleep(time.Millisecond * 10)
+}
+
+func TestExecuteAppWithArgs(t *testing.T) {
+ notiChan := make(chan string)
+
+ args := []string{"-ail"}
+ _, err := ExecuteApp(targetLocalAddr, serviceName, args, notiChan)
+ retError(t, err)
+
+ time.Sleep(time.Millisecond * 10)
+}
+
+func TestHandleNoti(t *testing.T) {
+ notiChan := make(chan string, 1)
+
+ id, err := ExecuteApp(targetLocalAddr, serviceName, nil, notiChan)
+ retError(t, err)
+
+ statusNotificationRequest := make(map[string]interface{})
+ statusNotificationRequest["ServiceID"] = id
+ statusNotificationRequest["Status"] = ConstServiceStatusFinished
+
+ HandleNoti(statusNotificationRequest)
+
+ select {
+ case str := <-notiChan:
+ t.Log(str)
+ if strings.Compare(ConstServiceStatusFinished, str) != 0 {
+ t.Error()
+ }
+ }
+}
+
+// @ System Test
+// func systemtestExecuteRemoteApp(t *testing.T) {
+// _, err := ExecuteApp(ConstPrefixHTTP+targetRemoteDeviceAddr, serviceName, nil, nil)
+// retError(t, err)
+
+// time.Sleep(time.Millisecond * 10)
+// }
+
+// func systemtestExecuteRemoteAppFailed(t *testing.T) {
+// _, err := ExecuteApp(ConstPrefixHTTP+targetRemoteDeviceAddr, "main", nil, nil)
+
+// if err.Error() != "Failed" {
+// t.Error()
+// }
+
+// time.Sleep(time.Millisecond * 10)
+// }