Compare commits
10 Commits
ed01ead04d
...
bfbbb3f089
Author | SHA1 | Date | |
---|---|---|---|
bfbbb3f089 | |||
7d19ec0fa8 | |||
7a7643cfeb | |||
d47d2e8d97 | |||
4d1a0e1d57 | |||
bbfa138849 | |||
782d652c0d | |||
50dec05e6b | |||
39d32f39f4 | |||
40db3cd26e |
@ -4,7 +4,7 @@ name: default
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: static_analysis
|
- name: static_analysis
|
||||||
image: python:3
|
image: python:3.8
|
||||||
commands:
|
commands:
|
||||||
- pip3 install pylint bandit mccabe
|
- pip3 install pylint bandit mccabe
|
||||||
- pip3 install -r requirements.txt
|
- pip3 install -r requirements.txt
|
||||||
@ -13,6 +13,12 @@ steps:
|
|||||||
- find . -name "*.py" -exec python3 -m mccabe --min 3 '{}' + || if [ $? -eq 1 ]; then echo "you fail"; fi
|
- find . -name "*.py" -exec python3 -m mccabe --min 3 '{}' + || if [ $? -eq 1 ]; then echo "you fail"; fi
|
||||||
- bandit -r . + || if [ $? -eq 1 ]; then echo "you fail"; fi
|
- bandit -r . + || if [ $? -eq 1 ]; then echo "you fail"; fi
|
||||||
|
|
||||||
|
- name: unit_test
|
||||||
|
image: python:3.8
|
||||||
|
commands:
|
||||||
|
- pip3 install -r requirements.txt
|
||||||
|
- pytest test.py
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
image: docker:stable-dind
|
image: docker:stable-dind
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM python:3
|
FROM python:3.8
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
8
app.py
8
app.py
@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
import random
|
import random
|
||||||
import uuid
|
import uuid
|
||||||
import logging
|
import logging
|
||||||
@ -21,12 +23,14 @@ sentry_sdk.init("https://3fa5ae886ba1489092ad49a93cb419c1@sentry.kmlabz.com/9")
|
|||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
KNOWNCONSUMER = os.getenv("PRODUCER_KNOWNCONSUMER",'10.69.42.1')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
LOGGER.info("Producer started")
|
LOGGER.info("Producer started")
|
||||||
generateduuid = str(uuid)
|
generateduuid = str(uuid)
|
||||||
|
communicator = Communicator(currentconsumer=KNOWNCONSUMER, uuid=generateduuid)
|
||||||
LOGGER.debug(f"My uuid is {generateduuid}")
|
LOGGER.debug(f"My uuid is {generateduuid}")
|
||||||
consumerlocator = ConsumerLocator(uuid=generateduuid)
|
consumerlocator = ConsumerLocator(uuid=generateduuid, communicator=communicator)
|
||||||
communicator = Communicator(consumerlocator=consumerlocator,uuid=generateduuid)
|
|
||||||
messagesender = MessageSender(communicator=communicator)
|
messagesender = MessageSender(communicator=communicator)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import logging
|
import logging
|
||||||
import random
|
|
||||||
import requests
|
import requests
|
||||||
from consumerlocator import ConsumerLocator
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Communicator module
|
Communicator module
|
||||||
@ -21,13 +19,13 @@ class Communicator:
|
|||||||
Class handling low level communication with consumers.
|
Class handling low level communication with consumers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, consumerlocator: ConsumerLocator, uuid: str):
|
def __init__(self, currentconsumer: str, uuid: str):
|
||||||
"""
|
"""
|
||||||
Initialize object
|
Initialize object
|
||||||
:param consumerlocator:
|
:param consumerlocator:
|
||||||
:param uuid:
|
:param uuid:
|
||||||
"""
|
"""
|
||||||
self.consumerlocator=consumerlocator
|
self.currenctconsumer=currentconsumer
|
||||||
self.uuid = uuid
|
self.uuid = uuid
|
||||||
|
|
||||||
def sendmessage(self, message: str) -> None:
|
def sendmessage(self, message: str) -> None:
|
||||||
@ -36,7 +34,7 @@ class Communicator:
|
|||||||
:param message:
|
:param message:
|
||||||
:return: none
|
:return: none
|
||||||
"""
|
"""
|
||||||
currentconsumer=self.consumerlocator.getcurrentconsumer()
|
currentconsumer=self.currenctconsumer
|
||||||
LOGGER.debug(f"Sending message to {currentconsumer}")
|
LOGGER.debug(f"Sending message to {currentconsumer}")
|
||||||
requests.post(f'http://{currentconsumer}/log', json={'uuid': self.uuid, 'message': message})
|
requests.post(f'http://{currentconsumer}/log', json={'uuid': self.uuid, 'message': message})
|
||||||
|
|
||||||
@ -45,7 +43,7 @@ class Communicator:
|
|||||||
Get the list of available consumer from the current primary consumer.
|
Get the list of available consumer from the current primary consumer.
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
currentconsumer = self.consumerlocator.getcurrentconsumer()
|
currentconsumer = self.currenctconsumer
|
||||||
response = requests.get(f'http://{currentconsumer}/consumer')
|
response = requests.get(f'http://{currentconsumer}/consumer')
|
||||||
json = response.json()
|
json = response.json()
|
||||||
LOGGER.debug(f"List of currently available consumers: {json}")
|
LOGGER.debug(f"List of currently available consumers: {json}")
|
||||||
@ -56,9 +54,13 @@ class Communicator:
|
|||||||
Readiness probe primary consumer.
|
Readiness probe primary consumer.
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
currentconsumer = self.consumerlocator.getcurrentconsumer()
|
currentconsumer = self.currenctconsumer
|
||||||
|
try:
|
||||||
response = requests.get(f'http://{currentconsumer}/consumer')
|
response = requests.get(f'http://{currentconsumer}/consumer')
|
||||||
isavailable = response.status_code == 200
|
isavailable = response.status_code == 200
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.exception(e)
|
||||||
|
isavailable = False
|
||||||
LOGGER.debug(f"Current consumer availability: {isavailable}")
|
LOGGER.debug(f"Current consumer availability: {isavailable}")
|
||||||
return isavailable
|
return isavailable
|
||||||
|
|
||||||
@ -68,7 +70,19 @@ class Communicator:
|
|||||||
:param consumer:
|
:param consumer:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
response = requests.get(f'http://{consumer}/consumer')
|
response = requests.get(f'http://{consumer}/consumer')
|
||||||
isavailable = response.status_code == 200
|
isavailable = response.status_code == 200
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.exception(e)
|
||||||
|
isavailable = False
|
||||||
LOGGER.debug(f"Consumer {consumer} availability: {isavailable}")
|
LOGGER.debug(f"Consumer {consumer} availability: {isavailable}")
|
||||||
return isavailable
|
return isavailable
|
||||||
|
|
||||||
|
def set_currentconsumer(self,currenctconsumer):
|
||||||
|
"""
|
||||||
|
Set current consumer
|
||||||
|
:param currenctconsumer:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self.currenctconsumer=currenctconsumer
|
||||||
|
@ -13,6 +13,7 @@ __copyright__ = "Copyright 2020, GoldenPogácsa Team"
|
|||||||
__module_name__ = "consumerlocator"
|
__module_name__ = "consumerlocator"
|
||||||
__version__text__ = "1"
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
KNOWNCONSUMER = os.getenv("PRODUCER_KNOWNCONSUMER",'10.69.42.1')
|
||||||
|
|
||||||
class ConsumerLocator:
|
class ConsumerLocator:
|
||||||
|
|
||||||
@ -20,13 +21,13 @@ class ConsumerLocator:
|
|||||||
Manages the list of consumers.
|
Manages the list of consumers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, uuid: str):
|
def __init__(self, uuid: str, communicator: Communicator):
|
||||||
"""
|
"""
|
||||||
Initialize class.
|
Initialize class.
|
||||||
"""
|
"""
|
||||||
self.consumerlist = [{"Host": os.environ["KnownConsumer"], "State": True, "LastOk": datetime.datetime.now()}]
|
self.consumerlist = [{"Host": KNOWNCONSUMER, "State": True, "LastOk": datetime.datetime.now()}]
|
||||||
self.currentconsumer = self.consumerlist[0]
|
self.currentconsumer = self.consumerlist[0]
|
||||||
self.communicator = Communicator(consumerlocator=self,uuid=uuid)
|
self.communicator = communicator
|
||||||
|
|
||||||
def learnconsumerlist(self) -> None:
|
def learnconsumerlist(self) -> None:
|
||||||
""""
|
""""
|
||||||
@ -82,6 +83,7 @@ class ConsumerLocator:
|
|||||||
self.learnconsumerlist()
|
self.learnconsumerlist()
|
||||||
|
|
||||||
if self.currentconsumer is not None:
|
if self.currentconsumer is not None:
|
||||||
|
self.communicator.set_currentconsumer(self.currentconsumer["Host"])
|
||||||
return self.currentconsumer["Host"]
|
return self.currentconsumer["Host"]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
@ -28,10 +28,10 @@ class MessageSender:
|
|||||||
"""
|
"""
|
||||||
self.communicator = communicator
|
self.communicator = communicator
|
||||||
|
|
||||||
def randomstring(self, stringLength) -> str:
|
def randomstring(self, stringlength: int) -> str:
|
||||||
"""Generate a random string of fixed length """
|
"""Generate a random string of fixed length """
|
||||||
letters = string.ascii_lowercase
|
letters = string.ascii_lowercase
|
||||||
return ''.join(random.choice(letters) for i in range(stringLength))
|
return ''.join(random.choice(letters) for i in range(stringlength))
|
||||||
|
|
||||||
def sendmessage(self, message: str = "") -> None:
|
def sendmessage(self, message: str = "") -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
sentry_sdk
|
sentry_sdk
|
||||||
requests
|
requests
|
||||||
|
pytest
|
||||||
|
pytest-mock
|
||||||
|
pytest-httpserver
|
219
test.py
Normal file
219
test.py
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import re
|
||||||
|
import consumerlocator
|
||||||
|
import communicator
|
||||||
|
import messagesender
|
||||||
|
|
||||||
|
"""
|
||||||
|
Unit tests for producer module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "@tormakris"
|
||||||
|
__copyright__ = "Copyright 2020, GoldenPogácsa Team"
|
||||||
|
__module_name__ = "test"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
generateduuid = 'c959ad81-58f9-4445-aab4-8f3d68aee1ad'
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_string(mocker):
|
||||||
|
mocker.patch('communicator.Communicator')
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer="localhost",
|
||||||
|
uuid=generateduuid)
|
||||||
|
mess = messagesender.MessageSender(communicator=comm)
|
||||||
|
msg = mess.randomstring(stringlength=32)
|
||||||
|
assert isinstance(msg, str)
|
||||||
|
assert len(msg) == 32
|
||||||
|
|
||||||
|
|
||||||
|
def test_sendmessage(httpserver):
|
||||||
|
httpserver.expect_oneshot_request(
|
||||||
|
uri="/log",
|
||||||
|
method='POST',
|
||||||
|
data="{\"uuid\": \"c959ad81-58f9-4445-aab4-8f3d68aee1ad\", \"message\": \"SENDING\"}").respond_with_json(
|
||||||
|
{
|
||||||
|
"test": "ok"})
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer=f"127.0.0.1:{port}",
|
||||||
|
uuid=generateduuid)
|
||||||
|
mess = "SENDING"
|
||||||
|
ret = comm.sendmessage(message=mess)
|
||||||
|
assert ret is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_send_message(mocker):
|
||||||
|
mocker.patch('communicator.Communicator')
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer="127.0.0.1",
|
||||||
|
uuid=generateduuid)
|
||||||
|
mess = messagesender.MessageSender(communicator=comm)
|
||||||
|
messa = "SENDING"
|
||||||
|
msg = mess.sendmessage(message=messa)
|
||||||
|
assert msg is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_discoveravailableconsumers(httpserver):
|
||||||
|
httpserver.expect_oneshot_request(
|
||||||
|
uri="/consumer",
|
||||||
|
method='GET',
|
||||||
|
data="").respond_with_json(
|
||||||
|
["10.69.42.1", "10.10.10.10", "10.20.30.40"])
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer=f"127.0.0.1:{port}",
|
||||||
|
uuid=generateduuid)
|
||||||
|
ret = comm.discoveravailableconsumers()
|
||||||
|
assert isinstance(ret, list)
|
||||||
|
assert ret == ["10.69.42.1", "10.10.10.10", "10.20.30.40"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_isconsumeravailable(httpserver):
|
||||||
|
httpserver.expect_oneshot_request(
|
||||||
|
uri="/consumer",
|
||||||
|
method='GET',
|
||||||
|
data="").respond_with_json(
|
||||||
|
["10.69.42.1", "10.10.10.10", "10.20.30.40"])
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer=f"127.0.0.1:{port}",
|
||||||
|
uuid=generateduuid)
|
||||||
|
ret = comm.isconsumeravailable()
|
||||||
|
assert isinstance(ret, bool)
|
||||||
|
assert ret
|
||||||
|
|
||||||
|
ret2 = comm.isconsumeravailable()
|
||||||
|
assert isinstance(ret2, bool)
|
||||||
|
assert ret2 == False
|
||||||
|
|
||||||
|
comm2 = communicator.Communicator(
|
||||||
|
currentconsumer="127.0.0.1:69",
|
||||||
|
uuid=generateduuid)
|
||||||
|
|
||||||
|
ret3 = comm2.isconsumeravailable()
|
||||||
|
assert isinstance(ret3, bool)
|
||||||
|
assert ret3 == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_checkconsumer(httpserver):
|
||||||
|
httpserver.expect_oneshot_request(
|
||||||
|
uri="/consumer",
|
||||||
|
method='GET',
|
||||||
|
data="").respond_with_json(
|
||||||
|
["10.69.42.1", "10.10.10.10", "10.20.30.40"])
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer="127.0.0.1",
|
||||||
|
uuid=generateduuid)
|
||||||
|
ret = comm.checkconsumer(f"127.0.0.1:{port}")
|
||||||
|
assert isinstance(ret, bool)
|
||||||
|
assert ret
|
||||||
|
|
||||||
|
ret2 = comm.checkconsumer(f"127.0.0.1:{port}")
|
||||||
|
assert isinstance(ret2, bool)
|
||||||
|
assert ret2 == False
|
||||||
|
|
||||||
|
comm2 = communicator.Communicator(
|
||||||
|
currentconsumer="127.0.0.1",
|
||||||
|
uuid=generateduuid)
|
||||||
|
|
||||||
|
ret3 = comm2.checkconsumer(f"127.0.0.1:{port}")
|
||||||
|
assert isinstance(ret3, bool)
|
||||||
|
assert ret3 == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_setcurrentconsumer():
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer="127.0.0.1",
|
||||||
|
uuid=generateduuid)
|
||||||
|
comm.set_currentconsumer("10.69.42.1")
|
||||||
|
assert comm.currenctconsumer == "10.69.42.1"
|
||||||
|
|
||||||
|
|
||||||
|
def test_learnconsumerlist(httpserver):
|
||||||
|
httpserver.expect_request(
|
||||||
|
uri="/consumer",
|
||||||
|
method='GET',
|
||||||
|
data="").respond_with_json(
|
||||||
|
["10.69.42.1", "10.10.10.10", "10.20.30.40"])
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer=f"127.0.0.1:{port}",
|
||||||
|
uuid=generateduuid)
|
||||||
|
consumerlocator.KNOWNCONSUMER = f"127.0.0.1:{port}"
|
||||||
|
locator = consumerlocator.ConsumerLocator(
|
||||||
|
uuid=generateduuid, communicator=comm)
|
||||||
|
ret = locator.learnconsumerlist()
|
||||||
|
assert ret is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_getcurrentconsumer(mocker):
|
||||||
|
mocker.patch('communicator.Communicator')
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer="127.0.0.1",
|
||||||
|
uuid=generateduuid)
|
||||||
|
locator = consumerlocator.ConsumerLocator(
|
||||||
|
uuid=generateduuid, communicator=comm)
|
||||||
|
assert locator.getcurrentconsumer() == consumerlocator.KNOWNCONSUMER
|
||||||
|
|
||||||
|
|
||||||
|
def test_checkcurrentconsumer(httpserver):
|
||||||
|
httpserver.expect_oneshot_request(
|
||||||
|
uri="/consumer",
|
||||||
|
method='GET',
|
||||||
|
data="").respond_with_json(
|
||||||
|
["10.69.42.1", "10.10.10.10", "10.20.30.40"])
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer=f"127.0.0.1:{port}",
|
||||||
|
uuid=generateduuid)
|
||||||
|
consumerlocator.KNOWNCONSUMER = f"127.0.0.1:{port}"
|
||||||
|
locator = consumerlocator.ConsumerLocator(
|
||||||
|
uuid=generateduuid, communicator=comm)
|
||||||
|
ret = locator.checkcurrentconsumer()
|
||||||
|
assert ret == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_updateconsumer(httpserver):
|
||||||
|
httpserver.expect_oneshot_request(
|
||||||
|
uri="/consumer",
|
||||||
|
method='GET',
|
||||||
|
data="").respond_with_json(
|
||||||
|
["10.69.42.1", "10.10.10.10", "10.20.30.40"])
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer=f"127.0.0.1:{port}",
|
||||||
|
uuid=generateduuid)
|
||||||
|
consumerlocator.KNOWNCONSUMER = f"127.0.0.1:{port}"
|
||||||
|
locator = consumerlocator.ConsumerLocator(
|
||||||
|
uuid=generateduuid, communicator=comm)
|
||||||
|
assert locator.currentconsumer is not None
|
||||||
|
ret = locator.updateconsumer()
|
||||||
|
assert ret == f"127.0.0.1:{port}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_updateconsumerlist(httpserver):
|
||||||
|
httpserver.expect_oneshot_request(
|
||||||
|
uri="/consumer",
|
||||||
|
method='GET',
|
||||||
|
data="").respond_with_json(
|
||||||
|
["10.69.42.1", "10.10.10.10", "10.20.30.40"])
|
||||||
|
url = httpserver.url_for("/")
|
||||||
|
port = re.match(r"\W*http[^:]*\D*(\d+)", url).group(1)
|
||||||
|
comm = communicator.Communicator(
|
||||||
|
currentconsumer=f"127.0.0.1:{port}",
|
||||||
|
uuid=generateduuid)
|
||||||
|
consumerlocator.KNOWNCONSUMER = f"127.0.0.1:{port}"
|
||||||
|
locator = consumerlocator.ConsumerLocator(
|
||||||
|
uuid=generateduuid, communicator=comm)
|
||||||
|
ret = locator.updateconsumerlist()
|
||||||
|
assert ret is None
|
Reference in New Issue
Block a user