import adhesive @adhesive.task("Notificare Succes") def notificare_succes(context: adhesive.Token) -> None: pass @adhesive.task("Backup {loop.value}") def backup_loop_value_(context: adhesive.Token) -> None: pass @adhesive.task("Arhivam serverul {loop,value}") def arhivam_serverul_loop_value_(context: adhesive.Token) -> None: pass adhesive.bpmn_build( "test.bpmn", initial_data={ "servers": ["a", "b", "c"], }, )
def pipeline(config: Optional[PipelineConfig] = None) -> None: script_dir = os.path.dirname(__file__) adhesive.bpmn_build(os.path.join(script_dir, "build_node.bpmn"), initial_data={})
import adhesive import time @adhesive.message("Generate events") def message_generate_events(context: adhesive.Token): for i in range(4): yield { "id": "a", "index": i, } time.sleep(1) @adhesive.task("Deduplicate Task on {event.id}", deduplicate="event.id") def deduplicate_task(context: adhesive.Token) -> None: time.sleep(2) @adhesive.task("Fail first execution") def fail_first_execution(context: adhesive.Token) -> None: if context.data.event["index"] == 0: raise Exception("task failed") adhesive.bpmn_build("deduplicate_fail_downstream.bpmn", wait_tasks=False)
import adhesive from adhesive.workspace import docker @adhesive.lane("Docker Container") def lane_docker_container(context): with docker.inside(context.workspace, "ubuntu:19.04") as w: yield w @adhesive.task(re="^Touch File: (.*)$") def touch_file(context, file_name): context.workspace.run(f""" touch {file_name} """) @adhesive.task(re="^Check if File Exists: (.*)$") def check_file_exists(context, file_name): print(context.workspace) context.workspace.run(f""" ls -l {file_name} """) adhesive.bpmn_build("lane.bpmn")
def create_secret_ingress_object_(context: adhesive.Token) -> None: pass @adhesive.task("Log Error") def log_error(context: adhesive.Token[Data]) -> None: pass @adhesive.task("Exit with error") def exit_with_error(context: adhesive.Token) -> None: sys.exit(2) def wait_for_url(url: str) -> None: pass domain_names = "domain.com" kubernetes_namespace = "test" ingress_object_name = "test" adhesive.bpmn_build( "new-certificate.bpmn", initial_data={ "namespace": kubernetes_namespace, "domain_names": domain_names.split(" "), "ingress_object": ingress_object_name, }, )
import adhesive import time @adhesive.message("Generate events every hour") def message_generate_events_every_hour(context: adhesive.Token): message_data = "data" for i in range(2): yield message_data time.sleep(3600) @adhesive.task("Fail the process") def fail_the_process(context: adhesive.Token) -> None: raise Exception("fail the process") adhesive.bpmn_build("event-failure.bpmn")
import adhesive import time import unittest test = unittest.TestCase() @adhesive.task("Sleep 2 Seconds") def sleep_2_seconds(context): time.sleep(2) @adhesive.task("Timeout was Called") def timeout_was_called(context): context.data.timeout_was_called = True data = adhesive.bpmn_build("one-second-timeout.bpmn", wait_tasks=False) test.assertTrue(data.timeout_was_called, "Timeout was not called :(")
@adhesive.task("Sleep 2 Seconds") def sleep_2_seconds(context: adhesive.Token) -> None: context.workspace.run(""" sleep 2 """) @adhesive.task("Timeout Happened") def timeout_happened(context: adhesive.Token) -> None: context.data.timeout_happened = True @adhesive.task("Should Not Execute") def should_not_execute(context: adhesive.Token) -> None: raise Exception("Should not be called") @adhesive.task("Error Happened") def error_happened(context: adhesive.Token) -> None: context.data.error_happened = True context.data._error = None data = adhesive.bpmn_build("cancel-boundary.bpmn") test.assertTrue(data.timeout_happened) test.assertFalse(data.error_happened, "The error boundary event was triggered on timeout") test.assertFalse(data._error, "An exception happened in the process")
import adhesive @adhesive.task(re='List files in (.*)') def list_files_in_folder(context, folder): context.workspace.run(f""" ls {folder} """) @adhesive.task('Check if /etc/passwd is present') def check_if_etc_passwd_is_present(context): # a return code different than 0 will throw an exception context.workspace.run(""" ls /etc/passwd """) adhesive.bpmn_build("simple.bpmn")
import unittest test = unittest.TestCase() @adhesive.task("Raise Error {loop.index}") def raise_error_loop_index_(context: adhesive.Token) -> None: raise Exception(f"error for {context.loop.index}") @adhesive.task("Error Caught") def error_caught(context: adhesive.Token) -> None: context.data.errors_caught = {str(uuid.uuid4())} @adhesive.task("Should Not Be Reachable") def should_not_be_reachable(context: adhesive.Token) -> None: raise Exception("Should not be reachable") data = adhesive.bpmn_build( "loop_exceptions.bpmn", wait_tasks=False, initial_data={ "items": range(20), }, ) test.assertTrue(data.errors_caught) test.assertEqual(1, len(data.errors_caught))
@adhesive.task("Check the file") def check_the_file(context): context.workspace.run(""" ls -l /tmp/test.txt """) @adhesive.lane("Noop") def lane_noop(context): with noop.inside(context.workspace) as w: try: print("==> noop") yield w finally: print("<== noop") @adhesive.lane("Docker") def lane_docker(context): with docker.inside(context.workspace, "ubuntu:19.04") as w: try: print("==> docker") yield w finally: print("<== docker") adhesive.bpmn_build("nested.bpmn")
import uuid import unittest test = unittest.TestCase() @adhesive.message("Generate Events") def message_generate_events(context: adhesive.Token): for i in range(4): time.sleep(0.3) yield { "id": "abc", "index": i, } @adhesive.task("Deduplicate event on id", deduplicate="event.id") def deduplicate_event_on_id(context: adhesive.Token) -> None: pass @adhesive.task("Task") def task(context: adhesive.Token) -> None: time.sleep(1) context.data.executions = {str(uuid.uuid4())} data = adhesive.bpmn_build("downstream-calls.bpmn", wait_tasks=False) test.assertEqual(2, len(data.executions))
retry_count = 6 while retry_count > 0: try: r = requests.get("http://localhost:5000/health") if r.status_code != 200: raise Exception("problem") if r.text != "ok": raise Exception("wrong text") retry_count = -1 break except Exception as e: pass retry_count -= 1 time.sleep(0.4) requests.get("http://localhost:5000/") requests.get("http://localhost:5000/") requests.get("http://localhost:5000/") requests.get("http://localhost:5000/rest/start-build") data = adhesive.bpmn_build("rest-endpoint.bpmn", wait_tasks=False) test.assertTrue(data.ran_tasks, "We have no data back") test.assertEqual(3, len(data.ran_tasks["Process Root Event"])) test.assertEqual(1, len(data.ran_tasks["Process Build Event"]))
@adhesive.task("Run mypy") def run_mypy(context): pass @adhesive.task("Prepare build") def prepare_build(context): pass @adhesive.task("GBS Build {loop.value.name}") def gbs_build_loop_value_name_(context): context.data.past_builds = {str(uuid.uuid4())} data = adhesive.bpmn_build( "build_python.bpmn", initial_data=addict.Dict({ "build": { "run_mypy": True, "run_flake8": True, "binaries": [{ "name": "x" }] } }), ) test.assertEqual(1, len(data.past_builds), "The builds were executed too many times")
w.pwd = "/tmp" w.write_file("test.txt", "yay") test_content = w.run("cat test.txt", capture_stdout=True) assert "yay" == test_content @adhesive.task("Shutdown\ Server") def shutdown_server(context): print("shutting down server...") context.workspace.run(f"docker rm -f {context.data.container_id}") print("[OK] server was shutdown") @adhesive.task("Test\ Failed") def test_failed(context): print(context.data.as_dict()) context.data.test_failed = True @adhesive.task("Check\ if\ test\ failed") def check_if_test_failed(context): if context.data._error: print("Uh oh, we got an error in the ssh execution") print(context.data._error) assert not context.data.test_failed adhesive.bpmn_build("ssh.bpmn")
@adhesive.task("Populate Selected Builds") def populate_selected_builds(context) -> None: context.data.start_times = dict() context.data.selected_builds = { "ucsj": "git://ucsj", "srv-core": "git://srv-core", "libcpprnt": "git://libcpprnt", } @adhesive.task(re="^bob: (.*)$") def bob_build(context, project_name) -> None: if project_name not in context.data.selected_builds: return if project_name not in context.data.start_times: context.data.start_times[project_name] = list() context.data.start_times[project_name].append( int(round(time.time() * 1000))) time.sleep(1) @adhesive.task("tc: awi") def tc_build(context) -> None: pass adhesive.bpmn_build("syncfun_debug.bpmn")
import unittest test = unittest.TestCase() @adhesive.message("Generate Events") def message_generate_events(context: adhesive.Token): message_ids = ["a", "a", "b", "a", "a", "a", "a", "b"] for i in range(len(message_ids)): yield { "id": message_ids[i], "event_index": str(i), } @adhesive.task("Event Check {event.id}") def event_check(context: adhesive.Token) -> None: pass @adhesive.task("Event Execute {event.id}", deduplicate="event.id") def event_execute(context: adhesive.Token) -> None: context.data.executed = {context.data.event["id"]} data = adhesive.bpmn_build( "deduplicate-multiple-bug.bpmn", wait_tasks=False, ) test.assertEqual({"a", "b"}, data.executed)
import adhesive import uuid import unittest import logging import time LOG = logging.getLogger(__name__) test = unittest.TestCase() @adhesive.message("Generate Event") def message_generate_event(context): for i in range(5): yield i time.sleep(0.2) # we give it time so the process can exit @adhesive.task("Process Event") def process_event(context): context.data.executions = set() context.data.executions.add(str(uuid.uuid4())) LOG.info(f"event data: {context.data.event}") data = adhesive.bpmn_build("basic-read.bpmn", wait_tasks=False) test.assertEqual(5, len(data.executions))
@adhesive.task("Build Docker Image") @cached_task.cached( params="args[0].data.current_version", ) def build_docker_image(context): context.workspace.run( f""" docker build -t germaniumhq/adhesive \\ -t germaniumhq/adhesive:{context.data.current_version} \\ . """ ) # FIXME: use secrets @adhesive.task("Publish Docker Image") @cached_task.cached( params="args[0].data.current_version", ) def publish_docker_image(context): context.workspace.run( f""" docker push germaniumhq/adhesive:{context.data.current_version} docker push germaniumhq/adhesive:latest """ ) adhesive.bpmn_build("adhesive-self.bpmn")
def run_flask_server(context): app.run() @adhesive.task('Create Resource') def create_resource(context): pass @adhesive.task('Update Resource') def update_resource(context): pass @adhesive.message_callback('REST: /rest/process-resource') def message_rest_rest_process_resource(context, callback): @app.route("/rest/resource/create") def create_resource(): callback(Dict({"type": "CREATE"})) return "Create event fired" @app.route("/rest/resource/process") def process_resource(): callback(Dict({"type": "PROCESS"})) return "Process event fired" adhesive.bpmn_build("rest-endpoint.bpmn")
import adhesive import time @adhesive.task('Potentially Long Running Task') def potentially_long_running_task(context): time.sleep(3) @adhesive.task('Notify Long Running Execution') def notify_long_running_execution(context): pass adhesive.bpmn_build( "timer-notification.bpmn", wait_tasks=False)
def hello_loop_value_(context): pass @adhesive.lane("server: {loop.value}") def lane_server_loop_value_(context): context.data.lane_names = set() context.data.lane_names.add(context.lane.name) context.data.lane_count += 1 yield context.workspace.clone() data = adhesive.bpmn_build( "parametrized-loop-workspace.bpmn", initial_data={ "items": ["a", "b", "c"], "lane_count": 0, }, ) test.assertEqual( data.lane_names, { "server: {loop.value}", }, "There should be a single lane for all the iterations", ) test.assertEqual(1, data.lane_count, "There should be a single lane for all the iterations")
if context.data.event["state"] == "done": context.data.event = pending_events[event_id] del pending_events[event_id] context.data.event["state"] = "process" already_running.add(event_id) return context.data @adhesive.task("Execute Task for {event_id}") def execute_task(context): context.data.executed_tasks.add(str(uuid.uuid4())) @adhesive.task("Set the event as processed") def set_the_event_as_processed(context): context.data.event["state"] = "done" data = adhesive.bpmn_build( "deduplicate.bpmn", wait_tasks=False, initial_data={ "executed_tasks": set(), }, ) # most events should be deduplicated test.assertTrue(len(data.executed_tasks) < 20)
import adhesive import unittest test = unittest.TestCase() @adhesive.task("Run Task in loop") def run_task_in_loop(context): context.data.count += context.loop.index result = adhesive.bpmn_build( "loop.bpmn", initial_data={ "items": ["1", "2", "3"], "count": 1, }, ) # execution should happen in parallel, any of the cases, the value would # be at most max index(2) + initial count(1) == 3 print(f"result count was {result.count}") test.assertTrue(result.count <= 3, "Loop execution went terribly wrong") test.assertTrue(result.count >= 1, "Loop execution went terribly wrong")
import adhesive import unittest test = unittest.TestCase() @adhesive.task("Task") def task(context): context.data.execution_count += 1 context.data.parallel_check += context.loop.index if context.loop.index >= 2: context.data.loop_condition = False data = adhesive.bpmn_build( "loop-parallel-condition.bpmn", initial_data={ "loop_condition": True, "execution_count": 0, "parallel_check": 1, }, ) test.assertEqual(3, data.execution_count) # 5 == 1 (initial value) + 0 + 1 + 2 test.assertEqual(4, data.parallel_check, "The loop probably didn't executed serially")
import adhesive @adhesive.message("Generate Events") def message_generate_events(context: adhesive.Token): yield { "id": "Resolved Id", "data": "Resolved Data", } @adhesive.task("Event Check {event.id}") def event_check_event_id_(context: adhesive.Token) -> None: pass @adhesive.task("Event Execute {event.data}") def event_execute_event_id_(context: adhesive.Token) -> None: pass adhesive.bpmn_build("message-interpolation-events.bpmn")
import adhesive @adhesive.task("Noop Task") def noop_task(context): pass @adhesive.task("Error Was Correctly Routed") def error_was_routed(context): context.data.error_was_routed = True data = adhesive.bpmn_build("test.bpmn") assert data.error_was_routed
import adhesive @adhesive.task("Sleep 2 seconds") def sleep_2_seconds(context: adhesive.Token) -> None: context.workspace.run(""" sleep 2 """) @adhesive.task("Should not execute") def should_not_execute(context: adhesive.Token) -> None: raise Exception("The timer should have cancelled the subprocess") adhesive.bpmn_build("cancel-subprocess.bpmn")