Skip to content
Snippets Groups Projects
Commit 34f7d0ee authored by Rodrigo Goncalves's avatar Rodrigo Goncalves Committed by Guilherme Arthur Gerônimo
Browse files

Container to run the integration test

parent 32668072
No related branches found
No related tags found
1 merge request!20Resolve "Data ingress for context information for tiki-wiki"
# Use an official Python runtime as a base image
FROM python:3.11-slim
# Set the working directory in the container
WORKDIR /app
# Copy the current directory contents into the container at /usr/src/app
COPY test.pem /app/client.pem
COPY test.key /app/client.key
COPY test-ingress.py /app/
COPY client.py /app/
COPY main.py /app/
# Install any needed packages specified in requirements.txt
RUN pip install requests
\ No newline at end of file
import mimetypes
import os
import requests
import json
class SmartDataContextAPIClient:
def __init__(self, cert_file, key_file, url="https://iot.lisha.ufsc.br/", verifyCertificate=True, logfile=None):
if not url.endswith('/'):
url += '/'
self._url = url
self._client = requests.Session()
self._client.cert = (cert_file, key_file)
self._client.verify = verifyCertificate
self._logfile = logfile
if not verifyCertificate:
requests.urllib3.disable_warnings()
def _log_request(self, method, url, headers, request_body, response_body):
if self._logfile:
with open(self._logfile, 'a') as log_file:
log_file.write(f"URL: {method} {url}\n")
log_file.write(f"Headers: {json.dumps(headers, indent=2)}\n")
if request_body:
log_file.write(f"Request Body: {json.dumps(request_body, indent=2)}\n")
log_file.write(f"Response Body: {response_body}\n")
log_file.write("\n" + "-"*50 + "\n")
def _doJsonPost(self, json_data, return_attribute = '', endpoint="api/v1_1/context.php"):
headers = {
'Content-Type': 'application/json'
}
url = self._url + endpoint
response = self._client.post(url, headers=headers, json=json_data)
try:
response_json = response.json()
self._log_request("POST", url, headers, json_data, response.json())
if "errors" in response_json:
raise Exception(f"Error processing request: {json.dumps(response_json['errors'])}")
else:
if return_attribute:
return response_json['result'][return_attribute]
else:
return response_json['result']
except Exception as e:
raise Exception(f"Invalid response from API: {response.content} - {e}")
def createSmartDataContext(self, content, features, t0=-1, t1=-1, smartDataSources=[], smartDataUnits=[]):
json_request = {
"command": "/create",
"request": {
"content": content,
"features": features,
"t0": t0,
"t1": t1,
"smartDataUnits": smartDataUnits,
"smartDataSouces": smartDataSources
}
}
return self._doJsonPost(json_request, 'smartDataContextId')
def associateSmartDataContext(self, smartDataContextIds, smartDataUnits=[], smartDataSources=[]):
if len(smartDataSources) == 0 and len(smartDataUnits) == 0:
raise Exception("At least one smartDataSource or smartDataUnit must be informed")
json_request = {
"command": "/associate",
"request": {
"smartDataContextIds": smartDataContextIds,
"smartDataUnits": smartDataUnits,
"smartDataSources": smartDataSources
}
}
result = self._doJsonPost(json_request)
if len(result) == 1:
return result[0]
else:
return result
def unassociateSmartDataContext(self, smartDataContextIds, smartDataUnits=[], smartDataSources=[]):
if len(smartDataSources) == 0 and len(smartDataUnits) == 0:
raise Exception("At least one smartDataSource or smartDataUnit must be informed")
json_request = {
"command": "/unassociate",
"request": {
"smartDataContextIds": smartDataContextIds,
"smartDataUnits": smartDataUnits,
"smartDataSources": smartDataSources
}
}
result = self._doJsonPost(json_request)
if len(result) == 1:
return result[0]
else:
return result
def getSmartDataContext(self, smartDataContextId):
json_request = {
"command": "/get",
"request": {
"smartDataContextId": smartDataContextId
}
}
return self._doJsonPost(json_request)
def findSmartDataContext(self, smartDataUnits=[], smartDataSources=[], t0=None, t1=None):
if len(smartDataSources) == 0 and len(smartDataUnits) == 0:
raise Exception("At least one smartDataSource or smartDataUnit must be informed")
json_request = {
"command": "/contexts",
"request": {
"smartDataUnits": smartDataUnits,
"smartDataSources": smartDataSources
}
}
if t0:
json_request['request']['t0'] = t0
if t1:
json_request['request']['t1'] = t1
return self._doJsonPost(json_request)
def querySmartDataContext(self, query):
json_request = {
"command": "/query",
"request": query
}
return self._doJsonPost(json_request)
def updateSmartDataContext(self, id, content=None, features=None, t0=None, t1=None, smartDataSources=None, smartDataUnits=None):
json_request = {
"command": "/update",
"request": {
"smartDataContextId": id
}
}
if content:
json_request['request']['content'] = content
if features:
json_request['request']['features'] = features
if t0:
json_request['request']['t0'] = t0
if t1:
json_request['request']['t1'] = t1
if smartDataSources:
json_request['request']['smartDataSources'] = smartDataSources
if smartDataUnits:
json_request['request']['smartDataUnits'] = smartDataUnits
return self._doJsonPost(json_request)
def addUnstructuredDataFromFile(self, smartDataContextId, filePath, fileName=None, mimeType=None):
if not fileName:
fileName = os.path.basename(filePath)
if not mimeType:
mimeType, _ = mimetypes.guess_type(filePath)
with open(filePath, 'rb') as f:
return self.addUnstructuredData(smartDataContextId, fileName, mimeType, f)
def addUnstructuredData(self, smartDataContextId, fileName, mimeType, data):
headers = {
'Content-Type': mimeType,
'Filename': fileName
}
url = self._url + f"api/v1_1/context.php?action=add-unstructured&smartDataContextId={smartDataContextId}"
response = self._client.post(url, headers=headers, data=data)
try:
response_json = response.json()
self._log_request("POST", url, headers, {"data": "binary data"}, response.json())
if "errors" in response_json:
raise Exception(f"Error processing request: {json.dumps(response_json['errors'])}")
else:
return response_json['result']['objectId']
except Exception as e:
raise Exception(f"Invalid response from API: {response.content} - {e}")
def getUnstructuredData(self, smartDataContextId, objectId):
headers = {
}
url = self._url + "api/v1_1/context.php"
json_request = {
"command": "/unstructured/get",
"request": {
"smartDataContextId": smartDataContextId,
"objectId": objectId
}
}
response = self._client.post(url, headers=headers, json=json_request)
try:
self._log_request("POST", url, dict(response.headers), json_request, "")
response.raise_for_status()
return response.content
except Exception as e:
raise Exception(f"Invalid response from API: {e}")
def saveUnstructuredDataToFile(self, smartDataContextId, objectId, filePath):
data = self.getUnstructuredData(smartDataContextId, objectId)
with open (filePath, "wb") as f:
f.write(data)
def removeUnstructuredData(self, smartDataContextId, objectId):
json_request = {
"command": "/unstructured/remove",
"request": {
"smartDataContextId": smartDataContextId,
"objectId": objectId
}
}
return self._doJsonPost(json_request)
\ No newline at end of file
import filecmp
import json
import os
from client import SmartDataContextAPIClient
CLIENT_CERTIFICATE="client.pem"
CLIENT_CERTIFICATE_KEY="client.key"
API_URL="https://web/"
def generate_random_file(filename, size_in_mb):
size_in_bytes = size_in_mb * 1024 * 1024
with open(filename, 'wb') as f:
f.write(os.urandom(size_in_bytes))
# Create a new SmartDataContextClient, passing a custom URL for the API and the certificates to access the domain
# The parameter verifyCertificate allows using self-signed certificates for development and test environments.
# Should not be used in production ideally
client = SmartDataContextAPIClient(cert_file=CLIENT_CERTIFICATE, key_file=CLIENT_CERTIFICATE_KEY, url=API_URL, verifyCertificate=False,
logfile="requests.log")
# Creates a new perene SmartDataContext (no start not end time). The minimum required parameters are the content
# and the features, with at least one feature (tags), which indicate tags to be associated with this SmartDataContext
# The function returns the create SmartDataContext id or throws an exception in case of error
pereneSmartDataContextId = client.createSmartDataContext(content={"meta": True}, features={"tags": ["sampleTag", "simulation"]})
print(f"Create a new SmartDataContext with id {pereneSmartDataContextId}")
# Now that we have a smartDataContext we can associate it to a SmartDataUnit or to SmartDataSource
# A smartDataUnit is represented by its value
# A smartDataSource is represented by its sphere (stationary) or its signature (mobile)
# Either smartDataUnits or smartDataSources or both can be associated to a smartDataContext
# A list of smartDataContextIds could be passed as well
# The function returns the list of updated SmartDataContext object or the single SmartDataContext
smartDataUnits = [0x84963924]
smartDataSources = [ [1,1,2,10], 'aeccd287']
pereneSmartDataContext = client.associateSmartDataContext(smartDataUnits=smartDataUnits, smartDataSources=smartDataSources, smartDataContextIds=pereneSmartDataContextId)
print(f"Updated SmartDataContext \n {json.dumps(pereneSmartDataContext, indent=2)}")
# To unassociate just call the unassociateSmartDataContext following the same syntax
smartDataSources = [ [1,1,2,10] ]
pereneSmartDataContext = client.unassociateSmartDataContext(smartDataSources=smartDataSources, smartDataContextIds=pereneSmartDataContextId)
print(f"Updated SmartDataContext \n {json.dumps(pereneSmartDataContext, indent=2)}")
# To retrieve a SmartDataContext by its id
pereneSmartDataContext = client.getSmartDataContext(smartDataContextId=pereneSmartDataContextId)
print(f"Retrieved SmartDataContext \n {json.dumps(pereneSmartDataContext, indent=2)}")
# To find all SmartDataContext associated to a set of smartDataSources or smartDataUnits
smartDataContextForSources = client.findSmartDataContext(smartDataSources=smartDataSources)
print(f"Retrieved SmartDataContext for {smartDataSources}: {len(smartDataContextForSources)} \n {json.dumps(smartDataContextForSources, indent=2)}")
smartDataContextForUnits = client.findSmartDataContext(smartDataUnits=smartDataUnits)
print(f"Retrieved SmartDataContext for {smartDataSources}: {len(smartDataContextForUnits)} \n {json.dumps(smartDataContextForUnits, indent=2)}")
smartDataContextForUnitsOrSources = client.findSmartDataContext(smartDataUnits=smartDataUnits, smartDataSources=smartDataSources)
print(f"Retrieved SmartDataContext for {smartDataSources} and {smartDataUnits}: {len(smartDataContextForUnitsOrSources)} \n {json.dumps(smartDataContextForUnitsOrSources, indent=2)}")
# To find all SmartDataContext associated to a set of smartDataSources or smartDataUnits under a time range
temporalSmartDataContextId = client.createSmartDataContext(content={"meta": True}, features={"tags": ["sampleTag", "simulation"]},
smartDataUnits=smartDataUnits, t0=15, t1=25)
temporalSmartDataContext = client.getSmartDataContext(smartDataContextId=temporalSmartDataContextId)
print(f"Retrieved temporal SmartDataContext \n {json.dumps(temporalSmartDataContext, indent=2)}")
smartDataContextForUnitsOrSources = client.findSmartDataContext(smartDataUnits=smartDataUnits, smartDataSources=smartDataSources, t0=16, t1=20)
print(f"Retrieved SmartDataContext for {smartDataSources} and {smartDataUnits} between 16 and 20 : {len(smartDataContextForUnitsOrSources)} \n {json.dumps(smartDataContextForUnitsOrSources, indent=2)}")
# To find all SmartDataContext associated to a set of smartDataSources or smartDataUnits under a time range
smartDataContextForUnitsOrSources = client.findSmartDataContext(smartDataUnits=smartDataUnits, smartDataSources=smartDataSources, t0=5, t1=9)
print(f"Retrieved SmartDataContext for {smartDataSources} and {smartDataUnits} between 5 and 9 : {len(smartDataContextForUnitsOrSources)} \n {json.dumps(smartDataContextForUnitsOrSources, indent=2)}")
# To do a generic query using the MongoDB syntax
query = {
"t0": 15
}
queryResult = client.querySmartDataContext(query)
print(f"Query result: \n {json.dumps(queryResult, indent=2)}")
# To change the contents of a SmartDataContext
temporalSmartDataContext = client.updateSmartDataContext(temporalSmartDataContextId, content={"meta": False})
print(f"Updated temporal SmartDataContext \n {json.dumps(temporalSmartDataContext, indent=2)}")
# To add an unstructured content to a SmartDataContext
generate_random_file("data.bin", 3)
storageObjectId = client.addUnstructuredDataFromFile(temporalSmartDataContextId, 'data.bin');
print(f"Stored object id is {storageObjectId}")
temporalSmartDataContext = client.getSmartDataContext(temporalSmartDataContextId);
print(f"Updated temporal SmartDataContext \n {json.dumps(temporalSmartDataContext, indent=2)}")
generate_random_file("data2.bin", 3)
storageObjectId2 = client.addUnstructuredDataFromFile(temporalSmartDataContextId, 'data2.bin');
print(f"Stored object id is {storageObjectId}")
temporalSmartDataContext = client.getSmartDataContext(temporalSmartDataContextId);
print(f"Updated temporal SmartDataContext \n {json.dumps(temporalSmartDataContext, indent=2)}")
# To retrieve an unstructured content from a SmartDataContent
client.saveUnstructuredDataToFile(temporalSmartDataContextId, storageObjectId, "data_retrieved.bin");
if filecmp.cmp("data.bin", "data_retrieved.bin"):
print("Retrieved file data.bin is identical\n")
else:
raise Exception("Retrieved file data.bin is not identical")
client.saveUnstructuredDataToFile(temporalSmartDataContextId, storageObjectId2, "data2_retrieved.bin");
if filecmp.cmp("data2.bin", "data2_retrieved.bin"):
print("Retrieved file data2.bin is identical\n")
else:
raise Exception("Retrieved file data2.bin is not identical")
os.remove("data_retrieved.bin")
os.remove("data2_retrieved.bin")
os.remove("data.bin")
os.remove("data2.bin")
# To remove a unstructured data
temporalSmartDataContext = client.removeUnstructuredData(temporalSmartDataContextId, storageObjectId)
print(f"Removed unstructured {storageObjectId} - containing unstructured count is {len(temporalSmartDataContext['unstructuredData'])} with id {temporalSmartDataContext['unstructuredData'][0]['id']}")
temporalSmartDataContext = client.removeUnstructuredData(temporalSmartDataContextId, storageObjectId2)
print(f"Removed unstructured {storageObjectId2} - containing unstructured count is {len(temporalSmartDataContext['unstructuredData'])}")
import filecmp
import json
import os
import sys
from client import SmartDataContextAPIClient
CLIENT_CERTIFICATE="client.pem"
CLIENT_CERTIFICATE_KEY="client.key"
API_URL="https://web/"
# Create a new SmartDataContextClient, passing a custom URL for the API and the certificates to access the domain
# The parameter verifyCertificate allows using self-signed certificates for development and test environments.
# Should not be used in production ideally
client = SmartDataContextAPIClient(cert_file=CLIENT_CERTIFICATE, key_file=CLIENT_CERTIFICATE_KEY, url=API_URL, verifyCertificate=False,
logfile="requests.log")
# To find all SmartDataContext associated with the vehicle
smartDataContextForSources = client.findSmartDataContext(smartDataSources=['a3edc4456f'])
print(f"Retrieved SmartDataContext for a3edc4456f: {len(smartDataContextForSources)} \n {json.dumps(smartDataContextForSources, indent=2)}")
if len(smartDataContextForSources) != 3:
sys.exit(1)
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEApsq6IteuqvTf0MuAIuOd3B5CowDpYq9Lu5K3h1dCXCT2bdHU
RK68e6yASt+M9n5FZwYdNakO3CY/KvRLUQkyQnuhnYTaIFtUlDJ/ZyEuskk3iaft
2rQpbzRl8nWK7L+7twrsq2jvEKf3qlPYcDoPdSO9NXIjO+2CrWmpS4u6Q3G8W5Ux
BnFqZNENE6Lh1dV7VY/gN/n/Ii3nyVn4w39428w3tZ4xxi0RxjB2Z5ccp6sTghsQ
POT3GuLx2c53x+/++e5KW/ycTq0dqfcbZgQOLfq8W8J9wVy9d6v1CRzspjKoPLKE
0J+JJFUPYx4xvkreQ+ugZaOO32tDSskKhAgDywIDAQABAoIBAGKZOUvboJ/jPmQZ
yNfXIry7Dr15jn4ODoEGDIRvawU5vIvTHN61RSr/IKAiYxxcLP7oOGA+XlB6M6Fa
5SM0goeWukV6AdBa7TbmWzZGAWrXqYMwyIUfN9dLbHDWV5f5CCj+xkXWNGzuPpRs
GGjPic+/ntx3aqjEkRmeerv0D9pJ76aR1N001y/KV65b8ksbE1nSlhPElfcXVHlH
d+RygfuQMaQkR/PAKEEzCbhAJ8J/Pr8pWLdT8JNdV77keqCwyRXIyatYGLGPlpmz
o7V+zPqnCIUzOL90VVZcFCyqAZPc4urW8ZGAIdOmEFPN+MrkxuTMDbKwmq+t+6h8
/t6kx6ECgYEA01CLOajY+5Ftvpaw4I2A7j/Tiy/bYr5y9dekuhLZVYRk2XWZuQaz
+SytAu0OtfqHdz/4wR1aqqtTWa3V5PiKlB+5yB9mhTLdBpgG+/tQ6HdZ9/j1JffO
9MBXibT6/5Ht4hC43ghe58aIzkTXdY4735C9QlyAVPRL05YPxCZaYjkCgYEAyg/1
ZK2vIoBUri2Fl8Zzgydui60POstVDjH2eDEaLoIWz5krroxu/HD/wFGrwLksAd7i
TnwBc4uhpyFbe4DVRqam2p83UhsBPOyg8ETmVA0O4p8sPqWPfzFoCnrGGi9bjX3i
+ISahwrUswZQe/sAKxt1nAncyoJAmUd6n7FZRiMCgYBsGl1PPxDaCbkB8mdEST+3
IpHfN7ldF58KI6qSwofKlvNcyCu/Gy3BAFj2ET4gXK0mlWR1rsWuX/1A+IxfGcMT
KfPJ7D5vT+kAsY+JIzVt53jwQb1wEgke7rMZsKtjSU1QBEv+0ntyyP89vrwW2I/K
vGoF4/qG+387HB6usww0CQKBgAXWIitvTOC9PjTtwa8Zn1qJeAr2y7rSBrnrPYhJ
Os1fGpOShA19pvMJvIlskn51mszPCFBmCpCw1tGCCCdwGDj7NVSZRrrLZuTAnQFz
rAd/fQ+Us2130MZGwg+TbkdxWL6khTrScbg22t/07bw3CtEz8Ni5/DOpQX5r7yHP
uJlrAoGBAJ54FrubIqitYAM+4bnv1gABKBNQnrqaQMWN6N2nxyICu7VH7nxqpr0s
41lM/ecwEoNm7hRP1PRKqq9/HULV/0IgduhkOo1koRl5c9FsLDoK+GHA+qbdwF5D
yDKoH/IJ3oUj8gaQPYwsxmAvX+My7gVGHs3ezjAzkAp5VQa5CPwo
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDMTCCAhkCFHYQTtvmyKXMa7sovZ5/68rBojgVMA0GCSqGSIb3DQEBCwUAMEUx
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjQwOTA1MTgxNTU4WhcNMjgxMDA1MTgx
NTU4WjBlMQswCQYDVQQGEwJCUjELMAkGA1UECAwCU0MxFjAUBgNVBAcMDUZsb3Jp
YW5vcG9saXMxDTALBgNVBAoMBFVGU0MxDjAMBgNVBAsMBUxpc2hhMRIwEAYDVQQD
DAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmyroi
166q9N/Qy4Ai453cHkKjAOlir0u7kreHV0JcJPZt0dRErrx7rIBK34z2fkVnBh01
qQ7cJj8q9EtRCTJCe6GdhNogW1SUMn9nIS6ySTeJp+3atClvNGXydYrsv7u3Cuyr
aO8Qp/eqU9hwOg91I701ciM77YKtaalLi7pDcbxblTEGcWpk0Q0TouHV1XtVj+A3
+f8iLefJWfjDf3jbzDe1njHGLRHGMHZnlxynqxOCGxA85Pca4vHZznfH7/757kpb
/JxOrR2p9xtmBA4t+rxbwn3BXL13q/UJHOymMqg8soTQn4kkVQ9jHjG+St5D66Bl
o47fa0NKyQqECAPLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEjKM4VVLY7xC+qj
s8W5W4dBx41fQm7Y1NNCzAZiag4SoC8eSLkiZ57TtNARmtT/jsdr0RlCusFQdhsJ
k42gHMXdL4vY1pcGp0OXXV5fDc9xPY74CoeLItuJHxwdNTwpxWsbXTu8bCl76SHF
9hgx1QToemFLPQqaE2E21SeF0+WVBpVzqaUCJjl+B5zzwfrAz9RHKwIGnf8EZEe2
2gfxsm1s29uT7KAOgOjwqZl8uzHCepHAbSKr5YcbbxjpNRzMWA6aeCnJ/4hoD3Rm
USDg885dgyTNlrhcAQV11yJMeXeQd6h/yOTkHCJlstpJfkcIhXsqRZUDgL69U/Z4
hwPfGdU=
-----END CERTIFICATE-----
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment