diff --git a/broker/Dockerfile_multiarch b/broker/Dockerfile_multiarch new file mode 100644 index 00000000..d685c6fa --- /dev/null +++ b/broker/Dockerfile_multiarch @@ -0,0 +1,5 @@ +FROM alpine +ARG TARGETOS +ARG TARGETARCH +ADD /${TARGETOS}/${TARGETARCH}/broker / +CMD ["/broker"] diff --git a/broker/build_k8s b/broker/build_k8s new file mode 100644 index 00000000..935045fa --- /dev/null +++ b/broker/build_k8s @@ -0,0 +1 @@ +docker buildx build --platform linux/arm,linux/arm64,linux/amd64 --push -f ./Dockerfile_multiarch -t "fogflow/broker:k8s" . diff --git a/designer/build_k8s b/designer/build_k8s new file mode 100644 index 00000000..15522942 --- /dev/null +++ b/designer/build_k8s @@ -0,0 +1 @@ +docker image tag fogflow/designer:latest fogflow/designer:k8s diff --git a/designer/config.json b/designer/config.json index 5d0fb92b..192d6ff3 100644 --- a/designer/config.json +++ b/designer/config.json @@ -28,7 +28,8 @@ }, "designer": { "webSrvPort": 8080, - "agentPort": 1030 + "agentPort": 1030, + "notRecreateSubscriptions": false }, "rabbitmq": { "port": 5672, diff --git a/designer/main.js b/designer/main.js index 081bc1dc..0e3eea52 100644 --- a/designer/main.js +++ b/designer/main.js @@ -68,6 +68,8 @@ if (!('host_ip' in globalConfigFile.broker)) { var cloudBrokerURL = "http://" + globalConfigFile.broker.host_ip + ":" + globalConfigFile.broker.http_port var ngsi10client = new NGSIClient.NGSI10Client(cloudBrokerURL + "/ngsi10"); +config.notRecreateSubscriptions = globalConfigFile.designer.notRecreateSubscriptions; + var recheck_interval = 2000; var timerID = setTimeout(function entityrestore(){ var url = cloudBrokerURL + "/version"; @@ -81,29 +83,58 @@ var timerID = setTimeout(function entityrestore(){ }); }); - // create the persistent subscriptions at the FogFlow Cloud Broker - Object.values(db.data.subscriptions).forEach(subscription => { - var headers = {}; - - if (subscription.destination_broker == 'NGSI-LD') { - headers["Content-Type"] = "application/json"; - headers["Destination"] = "NGSI-LD"; - headers["NGSILD-Tenant"] = subscription.tenant; - } else if (subscription.destination_broker == 'NGSIv2') { - headers["Content-Type"] = "application/json"; - headers["Destination"] = "NGSIv2"; - } - - var subscribeCtxReq = {}; - subscribeCtxReq.entities = [{ type: subscription['entity_type'], isPattern: true }]; - subscribeCtxReq.reference = subscription['reference_url']; - ngsi10client.subscribeContextWithHeaders(subscribeCtxReq, headers).then(function (subscriptionId) { - console.log("new subscription id = ", subscriptionId); - console.log(subscription) - }).catch(function (error) { - console.log('failed to subscribe context, ', error); - }); - }); + + if (!config.notRecreateSubscriptions){ + + fetch(cloudBrokerURL + "/ngsi10/subscription"). + then((response) => response.json()). + then(brokerSubscriptions => { + + Object.keys(db.data.subscriptions). + forEach(key => { + console.log("checking if the following subscription is already in the broker: ",key) + if(brokerSubscriptions.hasOwnProperty(key)) { + //delete designerSubscriptions[key]; + console.log("subscription already in the broker:", key) + } else { + + var subscription = db.data.subscriptions[key] + + var headers = {}; + + if (subscription.destination_broker == 'NGSI-LD') { + headers["Content-Type"] = "application/json"; + headers["Destination"] = "NGSI-LD"; + headers["NGSILD-Tenant"] = subscription.tenant; + } else if (subscription.destination_broker == 'NGSIv2') { + headers["Content-Type"] = "application/json"; + headers["Destination"] = "NGSIv2"; + } + + var subscribeCtxReq = {}; + subscribeCtxReq.entities = [{ type: subscription['entity_type'], isPattern: true }]; + subscribeCtxReq.reference = subscription['reference_url']; + // it is necessary to send them out not at the same time for having different subID + // since the subID is based on timestamp + var delayBeforeSend = Math.floor(Math.random() * 1000) + setTimeout(function(){ + //console.log("waited", delayBeforeSend); + ngsi10client.subscribeContextWithHeaders(subscribeCtxReq, headers).then(function (subscriptionId) { + console.log("new subscription id = ", subscriptionId); + console.log(subscription) + delete db.data.subscriptions[key]; + db.data.subscriptions[subscriptionId] = subscription + db.write(); + }).catch(function (error) { + console.log('failed to subscribe context, ', error); + }); + }, delayBeforeSend); + } + }); + }) + } else { + console.log("not recreating subscriptions ", config.notRecreateSubscriptions); + } }).catch(error=>{ console.log("try it again due to the error: ", error.code); @@ -420,6 +451,39 @@ app.post('/operator', jsonParser, async function (req, res) { res.sendStatus(200) }); +app.get('/dockerimage', async function (req, res) { + var operators = db.data.operators; + var dockers = {} + for (const [key, value] of Object.entries(operators)) { + if (value.hasOwnProperty('dockerimages') && value.dockerimages.length > 0){ + dockers.key = value + } + } + res.json(dockers); + +}); + +app.post('/dockerimage', jsonParser, async function (req, res) { + var dockerimages = req.body; + for (var i = 0; i < dockerimages.length; i++) { + var dockerimage = dockerimages[i]; + var operatorName = dockerimage.operatorName + + if (operatorName in db.data.operators) { + if (db.data.operators[operatorName].hasOwnProperty('dockerimages')){ + db.data.operators[operatorName].dockerimages.push(dockerimage) + } else { + db.data.operators[operatorName].dockerimages = [] + db.data.operators[operatorName].dockerimages.push(dockerimage) + } + } + } + + await db.write(); + + res.sendStatus(200) +}); + app.get('/dockerimage/:operator', async function (req, res) { var operatorName = req.params.operator; var operator = db.data.operators[operatorName]; @@ -430,8 +494,16 @@ app.post('/dockerimage/:operator', jsonParser, async function (req, res) { var operatorName = req.params.operator; var dockerimage = req.body; + console.log(operatorName in db.data.operators) + console.log(db.data.operators[operatorName]) + if (operatorName in db.data.operators) { - db.data.operators[operatorName].dockerimages.push(dockerimage) + if (db.data.operators[operatorName].hasOwnProperty('dockerimages')){ + db.data.operators[operatorName].dockerimages.push(dockerimage) + } else { + db.data.operators[operatorName].dockerimages = [] + db.data.operators[operatorName].dockerimages.push(dockerimage) + } } await db.write(); diff --git a/designer/public/js/function.js b/designer/public/js/function.js index 735e6b20..ea465fc8 100644 --- a/designer/public/js/function.js +++ b/designer/public/js/function.js @@ -31,7 +31,7 @@ $(function() { addMenuItem('FogFunction', 'Fog Function', showFogFunctions); //addMenuItem('TaskInstance', 'Task Instance', showTaskInstances); - //initFogFunctionExamples(); + initFogFunctionExamples(); showFogFunctions(); queryOperatorList(); diff --git a/designer/public/js/initialization.js b/designer/public/js/initialization.js index d058f01e..a4d1ea22 100644 --- a/designer/public/js/initialization.js +++ b/designer/public/js/initialization.js @@ -2,47 +2,58 @@ function defaultOperatorList(){ var operatorList = [{ name: "nodejs", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "python", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "iotagent", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "counter", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "anomaly", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "facefinder", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "connectedcar", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "recommender", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "privatesite", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "publicsite", description: "", - parameters: [] + parameters: [], + dockerimages: [] }, { name: "dummy", description: "", - parameters: [] + parameters: [], + dockerimages: [] }]; return operatorList; diff --git a/designer/public/js/operator.js b/designer/public/js/operator.js index 3ca3259d..1e95b8c1 100644 --- a/designer/public/js/operator.js +++ b/designer/public/js/operator.js @@ -4,11 +4,11 @@ $(function() { var handlers = {}; addMenuItem('Operator', 'Operator', showOperator); + + initOperatorList(); + initDockerImageList(); showOperator(); - - //initOperatorList(); - //initDockerImageList(); $(window).on('hashchange', function() { var hash = window.location.hash; @@ -51,6 +51,7 @@ $(function() { } function initOperatorList(){ + console.log("let's initialize the operator list") fetch('/operator').then(res => res.json()).then(opList => { if (Object.keys(opList).length === 0) { var operators = defaultOperatorList(); @@ -73,6 +74,27 @@ $(function() { }) } + function initDockerImageList(){ + console.log("Initialize docker images list") + fetch('/dockerimage').then(res => res.json()).then(imageList => { + if (Object.keys(imageList).length === 0) { + var images = defaultDockerImageList(); + fetch("/dockerimage", { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json" + }, + body: JSON.stringify(images) + }) + .then(response => { + console.log("send the initial list of docker images: ", response.status) + }) + .catch(err => console.log(err)); + } + }) + } + function queryOperatorList() { fetch('/operator').then(res => res.json()).then(operators => { Object.values(operators).forEach(operator => { @@ -109,7 +131,11 @@ $(function() { html += '' + operator.description + ''; html += ''; - html += operator.dockerimages.length; + if(operator.hasOwnProperty('dockerimages')){ + html += operator.dockerimages.length; + } else { + html += 0; + } html += ''; if ('parameters' in operator) { @@ -498,25 +524,7 @@ $(function() { //// }); // } -// function initDockerImageList(){ -// fetch('/dockerimage').then(res => res.json()).then(imageList => { -// if (Object.keys(imageList).length === 0) { -// var images = defaultDockerImageList(); -// fetch("/dockerimage", { -// method: "POST", -// headers: { -// Accept: "application/json", -// "Content-Type": "application/json" -// }, -// body: JSON.stringify(images) -// }) -// .then(response => { -// console.log("send the initial list of docker images: ", response.status) -// }) -// .catch(err => console.log(err)); -// } -// }) -// } + // function dockerImageRegistration() { // $('#info').html('New docker image registration'); diff --git a/designer/public/js/topology.js b/designer/public/js/topology.js index eb782d0d..6732e447 100644 --- a/designer/public/js/topology.js +++ b/designer/public/js/topology.js @@ -32,7 +32,7 @@ $(function() { addMenuItem('Topology', 'Service Topology', showTopologies); addMenuItem('Intent', 'Service Intent', showIntents); - //initTopologyExamples(); + initTopologyExamples(); showTopologies(); queryOperatorList(); diff --git a/discovery/build_k8s b/discovery/build_k8s new file mode 100644 index 00000000..41af573a --- /dev/null +++ b/discovery/build_k8s @@ -0,0 +1 @@ +docker image tag fogflow/discovery:latest fogflow/discovery:k8s diff --git a/master/build_k8s b/master/build_k8s new file mode 100644 index 00000000..e7d7e8b7 --- /dev/null +++ b/master/build_k8s @@ -0,0 +1 @@ +docker image tag fogflow/master:latest fogflow/master:k8s diff --git a/master/config.json b/master/config.json deleted file mode 120000 index 1ef8152a..00000000 --- a/master/config.json +++ /dev/null @@ -1 +0,0 @@ -../docker/core/http/local/config.json \ No newline at end of file diff --git a/release/latest/cloud/config.json b/release/latest/cloud/config.json index 37b40499..175d0996 100644 --- a/release/latest/cloud/config.json +++ b/release/latest/cloud/config.json @@ -1,5 +1,5 @@ { - "my_hostip": "172.17.0.1", + "my_hostip": "10.1.99.17", "physical_location":{ "longitude": 139, "latitude": 35 @@ -13,7 +13,7 @@ }, "discovery": { "http_port": 8090, - "storeOnDisk": false, + "storeOnDisk": true, "delayStoreOnFile" : 3 }, "broker": { diff --git a/release/latest/cloud/designerDB/db.json.baclup b/release/latest/cloud/designerDB/db.json.baclup new file mode 100644 index 00000000..2da758be --- /dev/null +++ b/release/latest/cloud/designerDB/db.json.baclup @@ -0,0 +1,55 @@ +{ + "devices": { + "62958e92-d39e-4b99-bb64-6627afefefff": { + "id": "62958e92-d39e-4b99-bb64-6627afefefff", + "type": "Temperature", + "attributes": { + "protocol": { + "type": "string", + "value": "NGSI-v1" + }, + "url": { + "type": "string", + "value": "http://172.17.0.1:8080/photo/null" + }, + "iconURL": { + "type": "string", + "value": "/photo/defaultIcon.png" + } + }, + "metadata": { + "location": { + "type": "point", + "value": { + "latitude": 38.02033965176977, + "longitude": -1.169400215148926 + } + } + }, + "entityId": { + "id": "62958e92-d39e-4b99-bb64-6627afefefff", + "type": "Temperature", + "isPattern": false + } + } + }, + "subscriptions": { + "c8f823bb-c186-11ed-b5dd-0242ac180005": { + "entity_type": "WeatherObserved", + "destination_broker": "NGSI-LD", + "reference_url": "http://172.17.0.1:7777", + "tenant": "ccoc" + }, + "b19e4b34-c1a2-11ed-a4a7-0242ac1b0005": { + "entity_type": "WeatherObserved", + "destination_broker": "NGSI-LD", + "reference_url": "http://172.17.0.1:7777", + "tenant": "ccoc" + } + }, + "operators": {}, + "topologies": {}, + "services": {}, + "serviceintents": {}, + "fogfunctions": {} +} \ No newline at end of file diff --git a/release/latest/cloud/docker-compose.yml b/release/latest/cloud/docker-compose.yml index b590af61..5b4651b2 100644 --- a/release/latest/cloud/docker-compose.yml +++ b/release/latest/cloud/docker-compose.yml @@ -1,20 +1,19 @@ version: "3" services: - designer: - image: fogflow/designer:latest - volumes: - - ./config.json:/app/config.json - - ./designerDB/:/app/public/data/meta/ - ports: - - 8080:8080 - - 1030:1030 - - 1090:1090 - depends_on: - - discovery - - cloud_broker -# - dgraph - - rabbitmq - restart: always +# designer: +# image: fogflow/designer:latest +# volumes: +# - ./config.json:/app/config.json +# - ./designerDB/:/app/public/data/meta/ +# ports: +# - 8080:8080 +# - 1030:1030 +# - 1090:1090 +# depends_on: +# - discovery +# - cloud_broker +# - rabbitmq +# restart: always discovery: image: fogflow/discovery:latest @@ -80,13 +79,3 @@ services: - discovery - cloud_broker restart: always - -# dgraph: -# image: dgraph/standalone -# volumes: -# - ./dgraph:/dgraph -# ports: -# - 6080:6080 -# - 8082:8080 -# - 9082:9080 -# - 8000:8000 diff --git a/release/latest/cloud/nginx.conf b/release/latest/cloud/nginx.conf index bcb97334..474430b6 100644 --- a/release/latest/cloud/nginx.conf +++ b/release/latest/cloud/nginx.conf @@ -7,9 +7,9 @@ http { listen 80; server_name www.fogflow.io; - location / { - proxy_pass http://designer:8080/; - } +# location / { +# proxy_pass http://designer:8080/; +# } location /ngsi9/ { proxy_pass http://discovery:8090/ngsi9/; diff --git a/worker/Dockerfile_multiarch b/worker/Dockerfile_multiarch new file mode 100644 index 00000000..70ea2e1a --- /dev/null +++ b/worker/Dockerfile_multiarch @@ -0,0 +1,6 @@ +FROM scratch +ARG TARGETOS +ARG TARGETARCH +ADD /${TARGETOS}/${TARGETARCH}/worker / +CMD ["/worker"] + diff --git a/worker/build_k8s b/worker/build_k8s new file mode 100644 index 00000000..970dd1f0 --- /dev/null +++ b/worker/build_k8s @@ -0,0 +1 @@ +docker buildx build --platform linux/arm,linux/arm64,linux/amd64 --push -f ./Dockerfile_multiarch -t "fogflow/worker:k8s" . diff --git a/worker/config.json b/worker/config.json deleted file mode 120000 index 1ef8152a..00000000 --- a/worker/config.json +++ /dev/null @@ -1 +0,0 @@ -../docker/core/http/local/config.json \ No newline at end of file