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

WIP: Add service discovery #920

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
32 changes: 32 additions & 0 deletions packages/services/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=services
PKG_VERSION=$(GIT_COMMIT_DATE)-$(GIT_COMMIT_TSTAMP)
GIT_COMMIT_DATE:=$(shell git log -n 1 --pretty=%ad --date=short . )
GIT_COMMIT_TSTAMP:=$(shell git log -n 1 --pretty=%at . )

include $(INCLUDE_DIR)/package.mk

define Package/$(PKG_NAME)
SUBMENU:=Services
SECTION:=net
CATEGORY:=Network
MAINTAINER:=Luandro <[email protected]>
TITLE:=Service discovery
DEPENDS:=
PKGARCH:=all
endef

define Package/$(PKG_NAME)/description
Services discovery for Community Networks.
endef

define Build/Compile
endef

define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/
$(CP) ./files/* $(1)/
endef

$(eval $(call BuildPackage,$(PKG_NAME)))
36 changes: 36 additions & 0 deletions packages/services/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Discoverable Services

## What

Exposes a `name`, `description`, `icon` and `ui` (port and path) for each service which had `APP_NAME`, `APP_DESCRIPTION`, `APP_ICON`, `APP_UI` addded to their [Balena environments]().

Should also accept other formats for Docker, docker-compose or native server setups, according to a manifest format.

## Architecture

1. Check connect clients on `/tmp/dhcp.leases`
1. For each client do `wget` on port `48484`
1. If json reponse, save it to `/tmp/services/{ip}.json`
1. Parse json and save a pruned version to `/www/cgi-bin/services`
1. Lime-App or other community-portals can easily fetch services data from `thisnode.info/www/cgi-bin/services`

## Opinions
- [Balena](https://balena.io) will be highly encouraged because:
- [Balena Hub](https://hub.balena.io/) has a growing number of out-of-the-box apps
- [Balena Cloud](https://balena-cloud.com) is free as long as project is published and used from Balena Hub
- simple migration from existing docker/docker-compose stack
- lightweight container-based operating system
- support for various types of single-board-computers and architectures
- over-the-air-updates
- small self-updating images
- per-device release pinning
- bulk monitoring of all devices and their services
- remote access to all devices and services via web terminal
- ssh tunnel & remote support
- Other docker stacks can work by adding an additional thin httpd image exposing the services manifest
- Native stacks can work by exposing services manifest

## Challenges

- Offline
- [Balena offline updates](https://www.balena.io/blog/offline-updates-make-it-easier-to-update-balena-devices-without-the-internet/)
2 changes: 2 additions & 0 deletions packages/services/files/etc/config/services
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
config base_config 'base_config'
option enabled '0'
21 changes: 21 additions & 0 deletions packages/services/files/etc/init.d/services
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh /etc/rc.common

START=99
NAME=services
PROG=/usr/bin/services

start() {
if [ $(uci get services.base_config.enabled) == 1 ]; then
logger -t services "Running services"
$PROG
# start
else
logger -t services "Services is disabled"
fi
}

stop () {
# stop
$PROG stop
logger -t pirania "Services stopped"
}
12 changes: 12 additions & 0 deletions packages/services/files/etc/uci-defaults/90-services-cron
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

unique_append()
{
grep -qF "$1" "$2" || echo "$1" >> "$2"
}

unique_append \
'*/10 * * * * ((services update &> /dev/null)&)'\
/etc/crontabs/root

exit 0
24 changes: 24 additions & 0 deletions packages/services/files/usr/bin/services
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh

update_services () {
}

# check if services are enabled in /etc/config/services
enabled=$(uci get services.base_config.enabled)

if [ "$1" = "start" ]; then
echo "Running services"
update_services
exit
elif [ "$1" = "update" ] ; then
update_services
exit
elif [ "$enabled" = "1" ]; then
update_services
exit
else
echo "Services are disabled. Try running services start"
exit

fi

28 changes: 28 additions & 0 deletions packages/services/files/usr/lib/lua/services/main.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/lua

local utils = require('lime.utils')

function services.list()
local services = {}
-- clients = read('/etc/dhcp.leases').get_ip()
-- mkirp /tmp/services
-- data = []
-- for client in $(clients) ; do
-- wget $client/v2/local/target-state proxy=on http_proxy=$client:48484 -O /tmp/services/$client.json
-- uci pirania set whitelist for $client?
-- done
-- for $server in $(/tmp/services/*)
-- finalServer = {}
-- services = []
-- server = json.parse(server)
-- finalServer.name = server.name
-- finalServer.id = server.id
-- finalServer.device = server.device
-- server.apps.map(app => finalServer.apps = name, ui, service, description, icon)
-- finalServer.apps = services
-- data.push(finalServer)
-- done
-- write(data, '/www/cgi-bin/services')
end

return services
43 changes: 43 additions & 0 deletions packages/services/files/usr/libexec/rpcd/services
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env lua
--[[
Copyright 2022 Luandro <[email protected]>
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-3.0
]]--
local ubus = require "ubus"
local json = require 'luci.jsonc'
local uci = require 'uci'
local services = require('services.main')
local utils = require('lime.utils')
local config = require('lime.config')

local uci_cursor = config.get_uci_cursor()

local conn = ubus.connect()
if not conn then
error("Failed to connect to ubus")
end

local function list_services()
-- services.list()
return utils.printJson({ status = 'ok', services = {}})
-- return utils.printJson({ status = services and 'ok' or 'error', services = services })
end

local methods = {
list = { no_params = 0 },
}

if arg[1] == 'list' then
utils.printJson(methods)
end

if arg[1] == 'call' then
local msg = utils.rpcd_readline()
msg = json.parse(msg)
if arg[2] == 'list' then list_services(msg)
else utils.printJson({ error = "Method not found" })
end
end
31 changes: 31 additions & 0 deletions packages/services/files/usr/share/rpcd/acl.d/services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"unauthenticated": {
"description": "services voucher public access",
"write": {
"ubus": {
"services": ["list"]
}
}
},
"lime-app": {
"description": "lime-app public access",
"read": {
"ubus": {
"services": ["list"]
}
}
},
"root": {
"description": "services administration access",
"write": {
"ubus": {
"services": ["*"]
}
},
"read": {
"ubus": {
"services": ["*"]
}
}
}
}