From 802d1b0a48c7690a0693d6e1c48d52e379bac522 Mon Sep 17 00:00:00 2001 From: James Wells Date: Fri, 26 Feb 2021 10:41:42 -0800 Subject: [PATCH 1/5] Going to trigger a build and test on the cluster. --- .drone.yml | 2 ++ gagent/main.go | 20 +++++++++++--- src/gstructs/gstructs.go | 8 +++--- src/worker/worker.go | 57 ++++++++++++++++++++-------------------- 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/.drone.yml b/.drone.yml index ead4160..2651a8a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -11,6 +11,8 @@ trigger: branch: include: - issues/1 + - issues/3 + - issues/4 exclude: - main diff --git a/gagent/main.go b/gagent/main.go index a182d45..dde2bcd 100644 --- a/gagent/main.go +++ b/gagent/main.go @@ -13,7 +13,7 @@ import ( // client "git.dragonheim.net/dragonheim/gagent/src/client" gr "git.dragonheim.net/dragonheim/gagent/src/router" - // worker "git.dragonheim.net/dragonheim/gagent/src/worker" + gw "git.dragonheim.net/dragonheim/gagent/src/worker" docopt "github.com/aviddiviner/docopt-go" hclsimple "github.com/hashicorp/hcl/v2/hclsimple" @@ -30,7 +30,6 @@ var exitCodes = struct { "AGENT_LOAD_FAILED": 4, "AGENT_MISSING_TAGS": 5, "NO_ROUTERS_DEFINED": 6, - "NO_WORKERS_DEFINED": 6, "NO_WORKERS_DEFINED": 7, }} @@ -149,6 +148,12 @@ func main() { log.Printf("Arguments are %v\n", arguments) log.Printf("Configuration is %v\n", config) log.Printf("Running in router mode\n") + + if len(config.Workers) == 0 { + log.Printf("No workers defined.\n") + os.Exit(exitCodes.m["NO_WORKERS_DEFINED"]) + } + go gr.Main(config) select {} @@ -161,8 +166,15 @@ func main() { */ log.Printf("Arguments are %v\n", arguments) log.Printf("Configuration is %v\n", config) - // go worker.Main(config) - // select {} + log.Printf("Running in worker mode\n") + + if len(config.Routers) == 0 { + log.Printf("No routers defined.\n") + os.Exit(exitCodes.m["NO_ROUTERS_DEFINED"]) + } + + go gw.Main(config) + select {} case "setup": log.Printf("Running in setup mode\n") diff --git a/src/gstructs/gstructs.go b/src/gstructs/gstructs.go index 03e24c0..ea5d3ea 100644 --- a/src/gstructs/gstructs.go +++ b/src/gstructs/gstructs.go @@ -5,8 +5,8 @@ type GagentConfig struct { Name string `hcl:"name,optional"` Mode string `hcl:"mode,attr"` UUID string `hcl:"uuid,optional"` - ListenAddr string `hcl:"address,optional"` - ListenPort int `hcl:"port,optional"` + ListenAddr string `hcl:"listenaddr,optional"` + ListenPort int `hcl:"listenport,optional"` Clients []*ClientDetails `hcl:"client,block"` Routers []*RouterDetails `hcl:"router,block"` Workers []*WorkerDetails `hcl:"worker,block"` @@ -43,7 +43,7 @@ type RouterDetails struct { * which MQ router to send the agent's requests to. * This attempts to keep the routers unique globally. */ - RouterID string `hcl:"routerid,attr"` + RouterID string `hcl:"uuid,attr"` /* * This is the IP Address and port that the router @@ -75,7 +75,7 @@ type WorkerDetails struct { * send agents to. This attempts to keep the * workers unique globally. */ - WorkerID string `hcl:"workerid,attr"` + WorkerID string `hcl:"uuid,attr"` /* * These tags will be passed to the router upon diff --git a/src/worker/worker.go b/src/worker/worker.go index e58b4de..464a674 100644 --- a/src/worker/worker.go +++ b/src/worker/worker.go @@ -2,7 +2,7 @@ package worker import ( "fmt" - // "log" + "log" "math/rand" "time" @@ -23,34 +23,8 @@ func pop(msg []string) (head, tail []string) { return } -// Main is the initiation function for a Worker -func Main(config gs.GagentConfig) { - // Frontend socket talks to clients over TCP - frontend, _ := zmq.NewSocket(zmq.ROUTER) - fmt.Printf("Running in worker mode\n") - - defer frontend.Close() - connectString := fmt.Sprintf("tcp://%s", config.Routers[0].RouterAddr) - frontend.Bind(connectString) - - // Backend socket talks to workers over inproc - backend, _ := zmq.NewSocket(zmq.DEALER) - defer backend.Close() - backend.Bind("inproc://backend") - - // Launch pool of agent handlers - for i := 0; i < 5; i++ { - go agentHandler(i) - } - - // Connect backend to frontend via a proxy - // err := zmq.Proxy(frontend, backend, nil) - // log.Fatalln("Proxy interrupted:", err) -} - // Each worker task works on one request at a time and sends a random number // of replies back, with random delays between replies: - func agentHandler(workerNum int) { interp := picol.InitInterp() interp.RegisterCoreCommands() @@ -70,8 +44,35 @@ func agentHandler(workerNum int) { // Sleep for some fraction of a second time.Sleep(time.Duration(rand.Intn(1000)+1) * time.Millisecond) - fmt.Println(fmt.Sprintf("Worker %d: %s", workerNum, identity)) + log.Printf(fmt.Sprintf("Worker %d: %s\n", workerNum, identity)) worker.SendMessage(identity, content) } } } + +// Main is the initiation function for a Worker +func Main(config gs.GagentConfig) { + // Frontend socket talks to clients over TCP + frontend, _ := zmq.NewSocket(zmq.ROUTER) + log.Printf("Starting worker\n") + + defer frontend.Close() + log.Printf("Attempting to connect to: %s(%s)\n", config.Routers[0].RouterName, config.Routers[0].RouterAddr) + connectString := fmt.Sprintf("tcp://%s", config.Routers[0].RouterAddr) + frontend.Bind(connectString) + + // Backend socket talks to workers over inproc + backend, _ := zmq.NewSocket(zmq.DEALER) + defer backend.Close() + backend.Bind("inproc://backend") + + // Launch pool of agent handlers + for i := 0; i < 5; i++ { + go agentHandler(i) + } + + // Connect backend to frontend via a proxy + // err := zmq.Proxy(frontend, backend, nil) + // log.Fatalln("Proxy interrupted:", err) +} + From cd9340af439a98ff2de22e5338062f1d64f4c6e6 Mon Sep 17 00:00:00 2001 From: James Wells Date: Fri, 26 Feb 2021 13:14:48 -0800 Subject: [PATCH 2/5] Updating the examples to match the current HCL structure. --- examples/example_gagent.hcl | 59 ++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/examples/example_gagent.hcl b/examples/example_gagent.hcl index 37d657d..3bc5ff5 100644 --- a/examples/example_gagent.hcl +++ b/examples/example_gagent.hcl @@ -24,6 +24,34 @@ name = "gagent-zulu.example.org" */ mode = "router" +/* + * This is the UUID used throughout the G'Agent system + * to uniquely identify this node. It is generated + * during setup. + * + * Required. + */ +uuid = "7e9d13fe-5151-5876-66c0-20ca03e8fca4" + +/* + * This is the IP Address to bind to, it defaults to + * 0.0.0.0 + * + * Optional. + * + * listenaddr = 0.0.0.0 + */ + +/. + * This is the port to listen on, it defaults to + * 33570. It is strongly recommended that you not + * use ports 0 - 1024 + * + * Optional. + * + * listenport = 33570 + */ + /* * This is the UUID used throughout the G'Agent system * to uniquely identify this node. @@ -32,6 +60,23 @@ mode = "router" */ // uuid = "04f97538-270d-4ca3-b782-e09ef35830e9" +/* + * This is the list of known G'Agent clients. Clients + * are not registered dynamically, instead the only + * clients that may connect are those listed here, + * but client's of other routers may route, via tags, + * their agent here. + * + * Optional. + */ +// client "alpha" { +// uuid = "04f97538-270d-4ce3-b782-e09ef35830e9" +// } +// +// client "beta" { +// uuid = "04f97538-270d-4cf3-b782-e09ef35830e9" +// } + /* * This is a list of known G'Agent routers. At least * one router is required for workers and clients. If @@ -39,19 +84,19 @@ mode = "router" * will connect to them in sequential order. */ // router "alpha" { -// routerid = "04f97538-270d-4cb3-b782-e09ef35830e9" +// uuid = "04f97538-270d-4cb3-b782-e09ef35830e9" // address = "gagent-alpha.example.org" // tags = [ "a", "b", "c", "d" ] // } // // router "beta" { -// routerid = "04f97538-270d-4cc3-b782-e09ef35830e9" +// uuid = "04f97538-270d-4cc3-b782-e09ef35830e9" // address = "gagent-beta.example.org" // tags = [ "a", "c", "e", "g" ] // } // // router "charlie" { -// routerid = "04f97538-270d-4cd3-b782-e09ef35830e9" +// uuid = "04f97538-270d-4cd3-b782-e09ef35830e9" // address = "gagent-charlie.example.org" // tags = [ "b", "d", "f", "h" ] // } @@ -64,20 +109,18 @@ mode = "router" * At least one worker is reuqired for routers. */ // worker "alpha" { -// workerid = "04f97538-270d-4ce3-b782-e09ef35830e9" +// uuid = "04f97538-270d-4ce3-b782-e09ef35830e9" // address = "gagent-alpha.example.org" // tags = [ "a", "b", "c", "d" ] // } // // worker "beta" { -// workerid = "04f97538-270d-4cf3-b782-e09ef35830e9" -// address = "gagent-beta.example.org" +// uuid = "04f97538-270d-4cf3-b782-e09ef35830e9" // tags = [ "a", "c", "e", "g" ] // } // // worker "charlie" { -// workerid = "04f97538-270d-4c04-b782-e09ef35830e9" -// address = "gagent-charlie.example.org" +// uuid = "04f97538-270d-4c04-b782-e09ef35830e9" // tags = [ "b", "d", "f", "h" ] // } From cd9d8f83147f34921cc6f95417e3767a1b76ad94 Mon Sep 17 00:00:00 2001 From: James Wells Date: Thu, 18 Mar 2021 15:53:40 -0700 Subject: [PATCH 3/5] fix: (issue/4) Removing inclusion limit in .drone.yml. --- .drone.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.drone.yml b/.drone.yml index 2651a8a..79f2f68 100644 --- a/.drone.yml +++ b/.drone.yml @@ -9,10 +9,6 @@ platform: trigger: branch: - include: - - issues/1 - - issues/3 - - issues/4 exclude: - main From 0eee4538139ea05f807e8470ec81b0a06c7786f1 Mon Sep 17 00:00:00 2001 From: James Wells Date: Wed, 31 Mar 2021 06:17:43 +0000 Subject: [PATCH 4/5] Testing drone on amd64 --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 79f2f68..15924ff 100644 --- a/.drone.yml +++ b/.drone.yml @@ -5,7 +5,7 @@ name: default platform: os: linux - arch: arm + arch: amd64 trigger: branch: From 8e56fdcb488f4e119a53b5b8243b748648f2ae1a Mon Sep 17 00:00:00 2001 From: James Wells Date: Fri, 2 Apr 2021 14:20:08 -0700 Subject: [PATCH 5/5] fix: (issues/4), Daemonize the worker. --- README.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1225532..adf70d6 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,39 @@ # G'Agent [![Build Status](https://drone.dragonheim.net/api/badges/dragonheim/gagent/status.svg)](https://drone.dragonheim.net/dragonheim/gagent) - A mobile agent system, written in Go, loosely inspired by the [Agent Tcl / D'Agents](http://www.cs.dartmouth.edu/~dfk/agents/) system created by Robert S. Gray of Dartmouth college. +## Purpose +As we move close and closer to a true space age, we need to start thinking about solutions for various light-speed issues such as the bi-directional time delay between the surface of Mars and the surface of Earth. At present it takes between 6 minutes and 44 minutes for single round-trip, making most current data services unuseable. G'Agent is a potential solution for data services given the time delay. + +Imagine, for a moment, that you are on Mars and need to perform a search for data in a specific domain space. You would have to explain it to someone on Earth, and hope they understand enough of the data / domain to know where to search and understand you well enough to perform the actual search and then send you the results. With G'Agent, instead you would write a basic script, hereafter called an agent, providing various hints as to the domain space as well as the actual search. Your client would then send it on to a server on Earth. The server, hereafter called a router, may or nothing about the domain space of your search, so the router will use the hints that you provide to attempt to route the request to other routers that may understand the specific domain space. Eventually your agent will reach a router whose servers, hereafter referred to as workers, can handle your search. The workers, will take the agent, run the script portion and collect the response(s). The worker will send the response back to the router(s) that it recieved the agent from, eventually routing it back to you. + +## Example Agent +```tcl +1 : ################### +2 : ### Hello Earth ### +3 : ################### +4 : # HINT START +5 : # - console +6 : # - gravity measurements +7 : # - gravity fluctuations +8 : # HINT END +9 : function hello_world() { +10: console.log("Hello Earth, does tempurature various alter specific gravity?") +11: } +12: console.log(hello_world()) +``` +Lines 1 - 3 are simple comments + +Line 4 Tells the G'Agent router that this is the start of the hints to route for. + +Lines 5 - 7 are a list of hints that the router will use to determine which router(s) may have domain specific information. + +Lines 9 - 11 are a tcl function that will be executed on the worker before sending the results back to the client. + +Line 12 executes the function defined above. + +## History More information can be found in the original [documentation](http://www.cs.dartmouth.edu/~dfk/agents/pub/agents/doc.5.1.ps.gz), and in the project's [wiki](https://git.dragonheim.net/dragonheim/gagent/wiki/_pages). We are adding Picol as a vendor package though we have modified it specific to support a subset of the [Agent Tcl / D'Agents](http://www.cs.dartmouth.edu/~dfk/agents/pub/agents/doc.5.1.ps.gz) language extensions. The language extensions can be found in the [LANGUAGE.md](https://git.dragonheim.net/dragonheim/gagent/src/branch/main/LANGUAGE.md) file.