flowtask 5.8.4__cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flowtask/__init__.py +93 -0
- flowtask/__main__.py +38 -0
- flowtask/bots/__init__.py +6 -0
- flowtask/bots/check.py +93 -0
- flowtask/bots/codebot.py +51 -0
- flowtask/components/ASPX.py +148 -0
- flowtask/components/AddDataset.py +352 -0
- flowtask/components/Amazon.py +523 -0
- flowtask/components/AutoTask.py +314 -0
- flowtask/components/Azure.py +80 -0
- flowtask/components/AzureUsers.py +106 -0
- flowtask/components/BaseAction.py +91 -0
- flowtask/components/BaseLoop.py +198 -0
- flowtask/components/BestBuy.py +800 -0
- flowtask/components/CSVToGCS.py +120 -0
- flowtask/components/CompanyScraper/__init__.py +1 -0
- flowtask/components/CompanyScraper/parsers/__init__.py +6 -0
- flowtask/components/CompanyScraper/parsers/base.py +102 -0
- flowtask/components/CompanyScraper/parsers/explorium.py +192 -0
- flowtask/components/CompanyScraper/parsers/leadiq.py +206 -0
- flowtask/components/CompanyScraper/parsers/rocket.py +133 -0
- flowtask/components/CompanyScraper/parsers/siccode.py +109 -0
- flowtask/components/CompanyScraper/parsers/visualvisitor.py +130 -0
- flowtask/components/CompanyScraper/parsers/zoominfo.py +118 -0
- flowtask/components/CompanyScraper/scrapper.py +1054 -0
- flowtask/components/CopyTo.py +177 -0
- flowtask/components/CopyToBigQuery.py +243 -0
- flowtask/components/CopyToMongoDB.py +291 -0
- flowtask/components/CopyToPg.py +609 -0
- flowtask/components/CopyToRethink.py +207 -0
- flowtask/components/CreateGCSBucket.py +102 -0
- flowtask/components/CreateReport/CreateReport.py +228 -0
- flowtask/components/CreateReport/__init__.py +9 -0
- flowtask/components/CreateReport/charts/__init__.py +15 -0
- flowtask/components/CreateReport/charts/bar.py +51 -0
- flowtask/components/CreateReport/charts/base.py +66 -0
- flowtask/components/CreateReport/charts/pie.py +64 -0
- flowtask/components/CreateReport/utils.py +9 -0
- flowtask/components/CustomerSatisfaction.py +196 -0
- flowtask/components/DataInput.py +200 -0
- flowtask/components/DateList.py +255 -0
- flowtask/components/DbClient.py +163 -0
- flowtask/components/DialPad.py +146 -0
- flowtask/components/DocumentDBQuery.py +200 -0
- flowtask/components/DownloadFrom.py +371 -0
- flowtask/components/DownloadFromD2L.py +113 -0
- flowtask/components/DownloadFromFTP.py +181 -0
- flowtask/components/DownloadFromIMAP.py +315 -0
- flowtask/components/DownloadFromS3.py +198 -0
- flowtask/components/DownloadFromSFTP.py +265 -0
- flowtask/components/DownloadFromSharepoint.py +110 -0
- flowtask/components/DownloadFromSmartSheet.py +114 -0
- flowtask/components/DownloadS3File.py +229 -0
- flowtask/components/Dummy.py +59 -0
- flowtask/components/DuplicatePhoto.py +411 -0
- flowtask/components/EmployeeEvaluation.py +237 -0
- flowtask/components/ExecuteSQL.py +323 -0
- flowtask/components/ExtractHTML.py +178 -0
- flowtask/components/FileBase.py +178 -0
- flowtask/components/FileCopy.py +181 -0
- flowtask/components/FileDelete.py +82 -0
- flowtask/components/FileExists.py +146 -0
- flowtask/components/FileIteratorDelete.py +112 -0
- flowtask/components/FileList.py +194 -0
- flowtask/components/FileOpen.py +75 -0
- flowtask/components/FileRead.py +120 -0
- flowtask/components/FileRename.py +106 -0
- flowtask/components/FilterIf.py +284 -0
- flowtask/components/FilterRows/FilterRows.py +200 -0
- flowtask/components/FilterRows/__init__.py +10 -0
- flowtask/components/FilterRows/functions.py +4 -0
- flowtask/components/GCSToBigQuery.py +103 -0
- flowtask/components/GoogleA4.py +150 -0
- flowtask/components/GoogleGeoCoding.py +344 -0
- flowtask/components/GooglePlaces.py +315 -0
- flowtask/components/GoogleSearch.py +539 -0
- flowtask/components/HTTPClient.py +268 -0
- flowtask/components/ICIMS.py +146 -0
- flowtask/components/IF.py +179 -0
- flowtask/components/IcimsFolderCopy.py +173 -0
- flowtask/components/ImageFeatures/__init__.py +5 -0
- flowtask/components/ImageFeatures/process.py +233 -0
- flowtask/components/IteratorBase.py +251 -0
- flowtask/components/LangchainLoader/__init__.py +5 -0
- flowtask/components/LangchainLoader/loader.py +194 -0
- flowtask/components/LangchainLoader/loaders/__init__.py +22 -0
- flowtask/components/LangchainLoader/loaders/abstract.py +362 -0
- flowtask/components/LangchainLoader/loaders/basepdf.py +50 -0
- flowtask/components/LangchainLoader/loaders/docx.py +91 -0
- flowtask/components/LangchainLoader/loaders/html.py +119 -0
- flowtask/components/LangchainLoader/loaders/pdfblocks.py +146 -0
- flowtask/components/LangchainLoader/loaders/pdfmark.py +79 -0
- flowtask/components/LangchainLoader/loaders/pdftables.py +135 -0
- flowtask/components/LangchainLoader/loaders/qa.py +67 -0
- flowtask/components/LangchainLoader/loaders/txt.py +55 -0
- flowtask/components/LeadIQ.py +650 -0
- flowtask/components/Loop.py +253 -0
- flowtask/components/Lowes.py +334 -0
- flowtask/components/MS365Usage.py +156 -0
- flowtask/components/MSTeamsMessages.py +320 -0
- flowtask/components/MarketClustering.py +1051 -0
- flowtask/components/MergeFiles.py +362 -0
- flowtask/components/MilvusOutput.py +87 -0
- flowtask/components/NearByStores.py +175 -0
- flowtask/components/NetworkNinja/__init__.py +6 -0
- flowtask/components/NetworkNinja/models/__init__.py +52 -0
- flowtask/components/NetworkNinja/models/abstract.py +177 -0
- flowtask/components/NetworkNinja/models/account.py +39 -0
- flowtask/components/NetworkNinja/models/client.py +19 -0
- flowtask/components/NetworkNinja/models/district.py +14 -0
- flowtask/components/NetworkNinja/models/events.py +101 -0
- flowtask/components/NetworkNinja/models/forms.py +499 -0
- flowtask/components/NetworkNinja/models/market.py +16 -0
- flowtask/components/NetworkNinja/models/organization.py +34 -0
- flowtask/components/NetworkNinja/models/photos.py +125 -0
- flowtask/components/NetworkNinja/models/project.py +44 -0
- flowtask/components/NetworkNinja/models/region.py +28 -0
- flowtask/components/NetworkNinja/models/store.py +203 -0
- flowtask/components/NetworkNinja/models/user.py +151 -0
- flowtask/components/NetworkNinja/router.py +854 -0
- flowtask/components/Odoo.py +175 -0
- flowtask/components/OdooInjector.py +192 -0
- flowtask/components/OpenFromXML.py +126 -0
- flowtask/components/OpenWeather.py +41 -0
- flowtask/components/OpenWithBase.py +616 -0
- flowtask/components/OpenWithPandas.py +715 -0
- flowtask/components/PGPDecrypt.py +199 -0
- flowtask/components/PandasIterator.py +187 -0
- flowtask/components/PandasToFile.py +189 -0
- flowtask/components/Paradox.py +339 -0
- flowtask/components/ParamIterator.py +117 -0
- flowtask/components/ParseHTML.py +84 -0
- flowtask/components/PlacerStores.py +249 -0
- flowtask/components/Pokemon.py +507 -0
- flowtask/components/PositiveBot.py +62 -0
- flowtask/components/PowerPointSlide.py +400 -0
- flowtask/components/PrintMessage.py +127 -0
- flowtask/components/ProductCompetitors/__init__.py +5 -0
- flowtask/components/ProductCompetitors/parsers/__init__.py +7 -0
- flowtask/components/ProductCompetitors/parsers/base.py +72 -0
- flowtask/components/ProductCompetitors/parsers/bestbuy.py +86 -0
- flowtask/components/ProductCompetitors/parsers/lowes.py +103 -0
- flowtask/components/ProductCompetitors/scrapper.py +155 -0
- flowtask/components/ProductCompliant.py +169 -0
- flowtask/components/ProductInfo/__init__.py +1 -0
- flowtask/components/ProductInfo/parsers/__init__.py +5 -0
- flowtask/components/ProductInfo/parsers/base.py +83 -0
- flowtask/components/ProductInfo/parsers/brother.py +97 -0
- flowtask/components/ProductInfo/parsers/canon.py +167 -0
- flowtask/components/ProductInfo/parsers/epson.py +118 -0
- flowtask/components/ProductInfo/parsers/hp.py +131 -0
- flowtask/components/ProductInfo/parsers/samsung.py +97 -0
- flowtask/components/ProductInfo/scraper.py +319 -0
- flowtask/components/ProductPricing.py +118 -0
- flowtask/components/QS.py +261 -0
- flowtask/components/QSBase.py +201 -0
- flowtask/components/QueryIterator.py +273 -0
- flowtask/components/QueryToInsert.py +327 -0
- flowtask/components/QueryToPandas.py +432 -0
- flowtask/components/RESTClient.py +195 -0
- flowtask/components/RethinkDBQuery.py +189 -0
- flowtask/components/Rsync.py +74 -0
- flowtask/components/RunSSH.py +59 -0
- flowtask/components/RunShell.py +71 -0
- flowtask/components/SalesForce.py +20 -0
- flowtask/components/SaveImageBank/__init__.py +257 -0
- flowtask/components/SchedulingVisits.py +592 -0
- flowtask/components/ScrapPage.py +216 -0
- flowtask/components/ScrapSearch.py +79 -0
- flowtask/components/SendNotify.py +257 -0
- flowtask/components/SentimentAnalysis.py +694 -0
- flowtask/components/ServiceScrapper/__init__.py +5 -0
- flowtask/components/ServiceScrapper/parsers/__init__.py +1 -0
- flowtask/components/ServiceScrapper/parsers/base.py +94 -0
- flowtask/components/ServiceScrapper/parsers/costco.py +93 -0
- flowtask/components/ServiceScrapper/scrapper.py +199 -0
- flowtask/components/SetVariables.py +156 -0
- flowtask/components/SubTask.py +182 -0
- flowtask/components/SuiteCRM.py +48 -0
- flowtask/components/Switch.py +175 -0
- flowtask/components/TableBase.py +148 -0
- flowtask/components/TableDelete.py +312 -0
- flowtask/components/TableInput.py +143 -0
- flowtask/components/TableOutput/TableOutput.py +384 -0
- flowtask/components/TableOutput/__init__.py +3 -0
- flowtask/components/TableSchema.py +534 -0
- flowtask/components/Target.py +223 -0
- flowtask/components/ThumbnailGenerator.py +156 -0
- flowtask/components/ToPandas.py +67 -0
- flowtask/components/TransformRows/TransformRows.py +507 -0
- flowtask/components/TransformRows/__init__.py +9 -0
- flowtask/components/TransformRows/functions.py +559 -0
- flowtask/components/TransposeRows.py +176 -0
- flowtask/components/UPCDatabase.py +86 -0
- flowtask/components/UnGzip.py +171 -0
- flowtask/components/Uncompress.py +172 -0
- flowtask/components/UniqueRows.py +126 -0
- flowtask/components/Unzip.py +107 -0
- flowtask/components/UpdateOperationalVars.py +147 -0
- flowtask/components/UploadTo.py +299 -0
- flowtask/components/UploadToS3.py +136 -0
- flowtask/components/UploadToSFTP.py +160 -0
- flowtask/components/UploadToSharepoint.py +205 -0
- flowtask/components/UserFunc.py +122 -0
- flowtask/components/VivaTracker.py +140 -0
- flowtask/components/WSDLClient.py +123 -0
- flowtask/components/Wait.py +18 -0
- flowtask/components/Walmart.py +199 -0
- flowtask/components/Workplace.py +134 -0
- flowtask/components/XMLToPandas.py +267 -0
- flowtask/components/Zammad/__init__.py +41 -0
- flowtask/components/Zammad/models.py +0 -0
- flowtask/components/ZoomInfoScraper.py +409 -0
- flowtask/components/__init__.py +104 -0
- flowtask/components/abstract.py +18 -0
- flowtask/components/flow.py +530 -0
- flowtask/components/google.py +335 -0
- flowtask/components/group.py +221 -0
- flowtask/components/py.typed +0 -0
- flowtask/components/reviewscrap.py +132 -0
- flowtask/components/tAutoincrement.py +117 -0
- flowtask/components/tConcat.py +109 -0
- flowtask/components/tExplode.py +119 -0
- flowtask/components/tFilter.py +184 -0
- flowtask/components/tGroup.py +236 -0
- flowtask/components/tJoin.py +270 -0
- flowtask/components/tMap/__init__.py +9 -0
- flowtask/components/tMap/functions.py +54 -0
- flowtask/components/tMap/tMap.py +450 -0
- flowtask/components/tMelt.py +112 -0
- flowtask/components/tMerge.py +114 -0
- flowtask/components/tOrder.py +93 -0
- flowtask/components/tPandas.py +94 -0
- flowtask/components/tPivot.py +71 -0
- flowtask/components/tPluckCols.py +76 -0
- flowtask/components/tUnnest.py +82 -0
- flowtask/components/user.py +401 -0
- flowtask/conf.py +457 -0
- flowtask/download.py +102 -0
- flowtask/events/__init__.py +11 -0
- flowtask/events/events/__init__.py +20 -0
- flowtask/events/events/abstract.py +95 -0
- flowtask/events/events/alerts/__init__.py +362 -0
- flowtask/events/events/alerts/colfunctions.py +131 -0
- flowtask/events/events/alerts/functions.py +158 -0
- flowtask/events/events/dummy.py +12 -0
- flowtask/events/events/exec.py +124 -0
- flowtask/events/events/file/__init__.py +7 -0
- flowtask/events/events/file/base.py +51 -0
- flowtask/events/events/file/copy.py +23 -0
- flowtask/events/events/file/delete.py +16 -0
- flowtask/events/events/interfaces/__init__.py +9 -0
- flowtask/events/events/interfaces/client.py +67 -0
- flowtask/events/events/interfaces/credentials.py +28 -0
- flowtask/events/events/interfaces/notifications.py +58 -0
- flowtask/events/events/jira.py +122 -0
- flowtask/events/events/log.py +26 -0
- flowtask/events/events/logerr.py +52 -0
- flowtask/events/events/notify.py +59 -0
- flowtask/events/events/notify_event.py +160 -0
- flowtask/events/events/publish.py +54 -0
- flowtask/events/events/sendfile.py +104 -0
- flowtask/events/events/task.py +97 -0
- flowtask/events/events/teams.py +98 -0
- flowtask/events/events/webhook.py +58 -0
- flowtask/events/manager.py +287 -0
- flowtask/exceptions.c +39393 -0
- flowtask/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/extensions/__init__.py +3 -0
- flowtask/extensions/abstract.py +82 -0
- flowtask/extensions/logging/__init__.py +65 -0
- flowtask/hooks/__init__.py +9 -0
- flowtask/hooks/actions/__init__.py +22 -0
- flowtask/hooks/actions/abstract.py +66 -0
- flowtask/hooks/actions/dummy.py +23 -0
- flowtask/hooks/actions/jira.py +74 -0
- flowtask/hooks/actions/rest.py +320 -0
- flowtask/hooks/actions/sampledata.py +37 -0
- flowtask/hooks/actions/sensor.py +23 -0
- flowtask/hooks/actions/task.py +9 -0
- flowtask/hooks/actions/ticket.py +37 -0
- flowtask/hooks/actions/zammad.py +55 -0
- flowtask/hooks/hook.py +62 -0
- flowtask/hooks/models.py +17 -0
- flowtask/hooks/service.py +187 -0
- flowtask/hooks/step.py +91 -0
- flowtask/hooks/types/__init__.py +23 -0
- flowtask/hooks/types/base.py +129 -0
- flowtask/hooks/types/brokers/__init__.py +11 -0
- flowtask/hooks/types/brokers/base.py +54 -0
- flowtask/hooks/types/brokers/mqtt.py +35 -0
- flowtask/hooks/types/brokers/rabbitmq.py +82 -0
- flowtask/hooks/types/brokers/redis.py +83 -0
- flowtask/hooks/types/brokers/sqs.py +44 -0
- flowtask/hooks/types/fs.py +232 -0
- flowtask/hooks/types/http.py +49 -0
- flowtask/hooks/types/imap.py +200 -0
- flowtask/hooks/types/jira.py +279 -0
- flowtask/hooks/types/mail.py +205 -0
- flowtask/hooks/types/postgres.py +98 -0
- flowtask/hooks/types/responses/__init__.py +8 -0
- flowtask/hooks/types/responses/base.py +5 -0
- flowtask/hooks/types/sharepoint.py +288 -0
- flowtask/hooks/types/ssh.py +141 -0
- flowtask/hooks/types/tagged.py +59 -0
- flowtask/hooks/types/upload.py +85 -0
- flowtask/hooks/types/watch.py +71 -0
- flowtask/hooks/types/web.py +36 -0
- flowtask/interfaces/AzureClient.py +137 -0
- flowtask/interfaces/AzureGraph.py +839 -0
- flowtask/interfaces/Boto3Client.py +326 -0
- flowtask/interfaces/DropboxClient.py +173 -0
- flowtask/interfaces/ExcelHandler.py +94 -0
- flowtask/interfaces/FTPClient.py +131 -0
- flowtask/interfaces/GoogleCalendar.py +201 -0
- flowtask/interfaces/GoogleClient.py +133 -0
- flowtask/interfaces/GoogleDrive.py +127 -0
- flowtask/interfaces/GoogleGCS.py +89 -0
- flowtask/interfaces/GoogleGeocoding.py +93 -0
- flowtask/interfaces/GoogleLang.py +114 -0
- flowtask/interfaces/GooglePub.py +61 -0
- flowtask/interfaces/GoogleSheet.py +68 -0
- flowtask/interfaces/IMAPClient.py +137 -0
- flowtask/interfaces/O365Calendar.py +113 -0
- flowtask/interfaces/O365Client.py +220 -0
- flowtask/interfaces/OneDrive.py +284 -0
- flowtask/interfaces/Outlook.py +155 -0
- flowtask/interfaces/ParrotBot.py +130 -0
- flowtask/interfaces/SSHClient.py +378 -0
- flowtask/interfaces/Sharepoint.py +496 -0
- flowtask/interfaces/__init__.py +36 -0
- flowtask/interfaces/azureauth.py +119 -0
- flowtask/interfaces/cache.py +201 -0
- flowtask/interfaces/client.py +82 -0
- flowtask/interfaces/compress.py +525 -0
- flowtask/interfaces/credentials.py +124 -0
- flowtask/interfaces/d2l.py +239 -0
- flowtask/interfaces/databases/__init__.py +5 -0
- flowtask/interfaces/databases/db.py +223 -0
- flowtask/interfaces/databases/documentdb.py +55 -0
- flowtask/interfaces/databases/rethink.py +39 -0
- flowtask/interfaces/dataframes/__init__.py +11 -0
- flowtask/interfaces/dataframes/abstract.py +21 -0
- flowtask/interfaces/dataframes/arrow.py +71 -0
- flowtask/interfaces/dataframes/dt.py +69 -0
- flowtask/interfaces/dataframes/pandas.py +167 -0
- flowtask/interfaces/dataframes/polars.py +60 -0
- flowtask/interfaces/db.py +263 -0
- flowtask/interfaces/env.py +46 -0
- flowtask/interfaces/func.py +137 -0
- flowtask/interfaces/http.py +1780 -0
- flowtask/interfaces/locale.py +40 -0
- flowtask/interfaces/log.py +75 -0
- flowtask/interfaces/mask.py +143 -0
- flowtask/interfaces/notification.py +154 -0
- flowtask/interfaces/playwright.py +339 -0
- flowtask/interfaces/powerpoint.py +368 -0
- flowtask/interfaces/py.typed +0 -0
- flowtask/interfaces/qs.py +376 -0
- flowtask/interfaces/result.py +87 -0
- flowtask/interfaces/selenium_service.py +779 -0
- flowtask/interfaces/smartsheet.py +154 -0
- flowtask/interfaces/stat.py +39 -0
- flowtask/interfaces/task.py +96 -0
- flowtask/interfaces/template.py +118 -0
- flowtask/interfaces/vectorstores/__init__.py +1 -0
- flowtask/interfaces/vectorstores/abstract.py +133 -0
- flowtask/interfaces/vectorstores/milvus.py +669 -0
- flowtask/interfaces/zammad.py +107 -0
- flowtask/models.py +193 -0
- flowtask/parsers/__init__.py +15 -0
- flowtask/parsers/_yaml.c +11978 -0
- flowtask/parsers/_yaml.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/argparser.py +235 -0
- flowtask/parsers/base.c +15155 -0
- flowtask/parsers/base.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/json.c +11968 -0
- flowtask/parsers/json.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/maps.py +49 -0
- flowtask/parsers/toml.c +11968 -0
- flowtask/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/plugins/__init__.py +16 -0
- flowtask/plugins/components/__init__.py +0 -0
- flowtask/plugins/handler/__init__.py +45 -0
- flowtask/plugins/importer.py +31 -0
- flowtask/plugins/sources/__init__.py +0 -0
- flowtask/runner.py +283 -0
- flowtask/scheduler/__init__.py +9 -0
- flowtask/scheduler/functions.py +493 -0
- flowtask/scheduler/handlers/__init__.py +8 -0
- flowtask/scheduler/handlers/manager.py +504 -0
- flowtask/scheduler/handlers/models.py +58 -0
- flowtask/scheduler/handlers/service.py +72 -0
- flowtask/scheduler/notifications.py +65 -0
- flowtask/scheduler/scheduler.py +993 -0
- flowtask/services/__init__.py +0 -0
- flowtask/services/bots/__init__.py +0 -0
- flowtask/services/bots/telegram.py +264 -0
- flowtask/services/files/__init__.py +11 -0
- flowtask/services/files/manager.py +522 -0
- flowtask/services/files/model.py +37 -0
- flowtask/services/files/service.py +767 -0
- flowtask/services/jira/__init__.py +3 -0
- flowtask/services/jira/jira_actions.py +191 -0
- flowtask/services/tasks/__init__.py +13 -0
- flowtask/services/tasks/launcher.py +213 -0
- flowtask/services/tasks/manager.py +323 -0
- flowtask/services/tasks/service.py +275 -0
- flowtask/services/tasks/task_manager.py +376 -0
- flowtask/services/tasks/tasks.py +155 -0
- flowtask/storages/__init__.py +16 -0
- flowtask/storages/exceptions.py +12 -0
- flowtask/storages/files/__init__.py +8 -0
- flowtask/storages/files/abstract.py +29 -0
- flowtask/storages/files/filesystem.py +66 -0
- flowtask/storages/tasks/__init__.py +19 -0
- flowtask/storages/tasks/abstract.py +26 -0
- flowtask/storages/tasks/database.py +33 -0
- flowtask/storages/tasks/filesystem.py +108 -0
- flowtask/storages/tasks/github.py +119 -0
- flowtask/storages/tasks/memory.py +45 -0
- flowtask/storages/tasks/row.py +25 -0
- flowtask/tasks/__init__.py +0 -0
- flowtask/tasks/abstract.py +526 -0
- flowtask/tasks/command.py +118 -0
- flowtask/tasks/pile.py +486 -0
- flowtask/tasks/py.typed +0 -0
- flowtask/tasks/task.py +778 -0
- flowtask/template/__init__.py +161 -0
- flowtask/tests.py +257 -0
- flowtask/types/__init__.py +8 -0
- flowtask/types/typedefs.c +11347 -0
- flowtask/types/typedefs.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/__init__.py +24 -0
- flowtask/utils/constants.py +117 -0
- flowtask/utils/encoders.py +21 -0
- flowtask/utils/executor.py +112 -0
- flowtask/utils/functions.cpp +14280 -0
- flowtask/utils/functions.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/json.cpp +13349 -0
- flowtask/utils/json.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/mail.py +63 -0
- flowtask/utils/parseqs.c +13324 -0
- flowtask/utils/parserqs.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/stats.py +308 -0
- flowtask/utils/transformations.py +74 -0
- flowtask/utils/uv.py +12 -0
- flowtask/utils/validators.py +97 -0
- flowtask/version.py +11 -0
- flowtask-5.8.4.dist-info/LICENSE +201 -0
- flowtask-5.8.4.dist-info/METADATA +209 -0
- flowtask-5.8.4.dist-info/RECORD +470 -0
- flowtask-5.8.4.dist-info/WHEEL +6 -0
- flowtask-5.8.4.dist-info/entry_points.txt +3 -0
- flowtask-5.8.4.dist-info/top_level.txt +2 -0
- plugins/components/CreateQR.py +39 -0
- plugins/components/TestComponent.py +28 -0
- plugins/components/Use1.py +13 -0
- plugins/components/Workplace.py +117 -0
- plugins/components/__init__.py +3 -0
- plugins/sources/__init__.py +0 -0
- plugins/sources/get_populartimes.py +78 -0
- plugins/sources/google.py +150 -0
- plugins/sources/hubspot.py +679 -0
- plugins/sources/icims.py +679 -0
- plugins/sources/mobileinsight.py +501 -0
- plugins/sources/newrelic.py +262 -0
- plugins/sources/uap.py +268 -0
- plugins/sources/venu.py +244 -0
- plugins/sources/vocinity.py +314 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
import asyncio
|
2
|
+
from datetime import datetime
|
3
|
+
import traceback
|
4
|
+
import socket
|
5
|
+
from asyncdb import AsyncDB
|
6
|
+
from ...conf import (
|
7
|
+
ENVIRONMENT,
|
8
|
+
TASK_EXEC_BACKEND,
|
9
|
+
TASK_EXEC_CREDENTIALS,
|
10
|
+
TASK_EVENT_TABLE,
|
11
|
+
INFLUX_DATABASE,
|
12
|
+
TASK_EXEC_TABLE,
|
13
|
+
USE_TASK_EVENT,
|
14
|
+
)
|
15
|
+
from ...utils.json import json_encoder
|
16
|
+
from .abstract import AbstractEvent
|
17
|
+
|
18
|
+
EVENT_HOST = socket.gethostbyname(socket.gethostname())
|
19
|
+
|
20
|
+
|
21
|
+
class LogExecution(AbstractEvent):
|
22
|
+
"""LogExecution.
|
23
|
+
|
24
|
+
Log the execution of a Task into a InfluxDB measurement bucket.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def get_influx(self):
|
28
|
+
return AsyncDB(
|
29
|
+
TASK_EXEC_BACKEND,
|
30
|
+
params=TASK_EXEC_CREDENTIALS,
|
31
|
+
loop=asyncio.get_event_loop(),
|
32
|
+
)
|
33
|
+
|
34
|
+
async def __call__(self, *args, **kwargs):
|
35
|
+
status = kwargs.pop("status", "event")
|
36
|
+
task = kwargs.pop("task", None)
|
37
|
+
cls = kwargs.pop("cls", None)
|
38
|
+
msg = kwargs.pop("message", str(cls))
|
39
|
+
if self.disable_notification is True:
|
40
|
+
return
|
41
|
+
if USE_TASK_EVENT is True:
|
42
|
+
try:
|
43
|
+
task_id = task.task_id
|
44
|
+
task_name = task.taskname
|
45
|
+
program = task.getProgram()
|
46
|
+
except (AttributeError, TypeError):
|
47
|
+
task_id = None
|
48
|
+
task_name = None
|
49
|
+
program = None
|
50
|
+
async with await self.get_influx().connection() as conn:
|
51
|
+
try:
|
52
|
+
# saving the log into metric database:
|
53
|
+
start_time = datetime.utcnow()
|
54
|
+
data = {
|
55
|
+
"measurement": TASK_EXEC_TABLE,
|
56
|
+
"location": ENVIRONMENT,
|
57
|
+
"timestamp": start_time,
|
58
|
+
"fields": {"status": status},
|
59
|
+
"tags": {
|
60
|
+
"host": EVENT_HOST,
|
61
|
+
"region": ENVIRONMENT,
|
62
|
+
"start_time": start_time,
|
63
|
+
"tenant": program,
|
64
|
+
"task": task_name,
|
65
|
+
"task_id": str(task_id),
|
66
|
+
"message": msg,
|
67
|
+
"traceback": str(traceback.format_exc()),
|
68
|
+
},
|
69
|
+
}
|
70
|
+
await conn.write(data, bucket=INFLUX_DATABASE)
|
71
|
+
except Exception as e:
|
72
|
+
self._logger.error(f"Flowtask: Error saving Task Execution: {e}")
|
73
|
+
|
74
|
+
|
75
|
+
class SaveExecution(LogExecution):
|
76
|
+
async def __call__(self, *args, **kwargs):
|
77
|
+
status = kwargs.pop("status", "event")
|
78
|
+
task = kwargs.pop("task", None)
|
79
|
+
cls = kwargs.pop("error", None)
|
80
|
+
err = getattr(cls, "message", str(cls))
|
81
|
+
msg = kwargs.pop("message", err)
|
82
|
+
if self.disable_notification is True:
|
83
|
+
return
|
84
|
+
if USE_TASK_EVENT is True:
|
85
|
+
try:
|
86
|
+
stat = task.stats # getting the stat object:
|
87
|
+
except AttributeError:
|
88
|
+
stats = None
|
89
|
+
if stat:
|
90
|
+
stats = json_encoder(stat.to_json())
|
91
|
+
start_time = stat.start_time
|
92
|
+
end_time = stat.finish_time
|
93
|
+
duration = stat.duration
|
94
|
+
else:
|
95
|
+
stats = {}
|
96
|
+
start_time = None
|
97
|
+
end_time = datetime.utcnow()
|
98
|
+
duration = None
|
99
|
+
async with await self.get_influx().connection() as conn:
|
100
|
+
try:
|
101
|
+
data = {
|
102
|
+
"measurement": TASK_EVENT_TABLE,
|
103
|
+
"location": ENVIRONMENT,
|
104
|
+
"timestamp": end_time,
|
105
|
+
"fields": {"status": status},
|
106
|
+
"tags": {
|
107
|
+
"host": EVENT_HOST,
|
108
|
+
"region": ENVIRONMENT,
|
109
|
+
"stats": stats,
|
110
|
+
"start_time": start_time,
|
111
|
+
"finish_time": end_time,
|
112
|
+
"duration": duration,
|
113
|
+
"tenant": task.getProgram(),
|
114
|
+
"task": task.taskname,
|
115
|
+
"id": task.task_id,
|
116
|
+
"traceback": traceback.format_exc(),
|
117
|
+
"message": msg,
|
118
|
+
},
|
119
|
+
}
|
120
|
+
await conn.write(data, bucket=INFLUX_DATABASE)
|
121
|
+
except Exception as e:
|
122
|
+
self._logger.error(
|
123
|
+
f"FlowTask: Error saving Task Execution: {e}"
|
124
|
+
)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
import glob
|
3
|
+
from pathlib import Path, PurePath
|
4
|
+
from ..abstract import AbstractEvent
|
5
|
+
|
6
|
+
|
7
|
+
class FileBase(AbstractEvent, ABC):
|
8
|
+
def __init__(self, *args, **kwargs):
|
9
|
+
self._filenames: list[PurePath] = []
|
10
|
+
super(FileBase, self).__init__(*args, **kwargs)
|
11
|
+
|
12
|
+
def start(self):
|
13
|
+
if hasattr(self, "directory"):
|
14
|
+
d = self.mask_replacement(
|
15
|
+
self.directory # pylint: disable=E0203
|
16
|
+
) # pylint: disable=access-member-before-definition
|
17
|
+
p = Path(d) # pylint: disable=E0203
|
18
|
+
if p.exists() and p.is_dir():
|
19
|
+
self.directory = p
|
20
|
+
else:
|
21
|
+
self._logger.error(f"Path doesn't exists: {self.directory}")
|
22
|
+
if hasattr(self, "destination"):
|
23
|
+
d = self.mask_replacement(
|
24
|
+
self.destination # pylint: disable=E0203
|
25
|
+
) # pylint: disable=access-member-before-definition
|
26
|
+
p = Path(d) # pylint: disable=E0203
|
27
|
+
if p.exists() and p.is_dir():
|
28
|
+
self.destination = p
|
29
|
+
else:
|
30
|
+
if hasattr(self, "create_destination"):
|
31
|
+
self.destination.mkdir(parents=True, exist_ok=True)
|
32
|
+
else:
|
33
|
+
self._logger.error(
|
34
|
+
f"Destination Path doesn't exists: {self.directory}"
|
35
|
+
)
|
36
|
+
if hasattr(self, "filename"):
|
37
|
+
if isinstance(self.filename, list):
|
38
|
+
for file in self.filename:
|
39
|
+
fname = self.mask_replacement(file)
|
40
|
+
self._filenames.append(self.directory.joinpath(fname))
|
41
|
+
elif isinstance(self.filename, PurePath):
|
42
|
+
self._filenames.append(self.filename)
|
43
|
+
elif isinstance(self.filename, str):
|
44
|
+
if "*" in self.filename:
|
45
|
+
path = self.directory.joinpath(self.filename)
|
46
|
+
listing = glob.glob(str(path)) # TODO using glob from pathlib
|
47
|
+
for fname in listing:
|
48
|
+
self._filenames.append(Path(fname))
|
49
|
+
else:
|
50
|
+
fname = self.mask_replacement(self.filename)
|
51
|
+
self._filenames.append(self.directory.joinpath(fname))
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import shutil
|
2
|
+
from .base import FileBase
|
3
|
+
|
4
|
+
|
5
|
+
class FileCopy(FileBase):
|
6
|
+
def __init__(self, *args, **kwargs):
|
7
|
+
self.move = kwargs.pop("move", False)
|
8
|
+
super(FileCopy, self).__init__(*args, **kwargs)
|
9
|
+
|
10
|
+
async def __call__(self, *args, **kwargs):
|
11
|
+
self.start()
|
12
|
+
for src in self._filenames:
|
13
|
+
dest = self.destination.joinpath(src.name)
|
14
|
+
if self.move:
|
15
|
+
shutil.move(src, dest)
|
16
|
+
# self._logger.info(
|
17
|
+
# f"Moved file {src} to {dest}"
|
18
|
+
# )
|
19
|
+
else:
|
20
|
+
shutil.copy2(src, dest)
|
21
|
+
# self._logger.info(
|
22
|
+
# f"Copied file {src} to {dest}"
|
23
|
+
# )
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from .base import FileBase
|
2
|
+
|
3
|
+
|
4
|
+
class FileDelete(FileBase):
|
5
|
+
async def __call__(self, *args, **kwargs):
|
6
|
+
self.start()
|
7
|
+
for filename in self._filenames:
|
8
|
+
if filename.exists() and filename.is_file():
|
9
|
+
try:
|
10
|
+
filename.unlink()
|
11
|
+
except Exception as e:
|
12
|
+
self._logger.error(f"Error deleting {filename}: {e}")
|
13
|
+
else:
|
14
|
+
self._logger.warning(
|
15
|
+
f"{filename} does not exist or is not a file."
|
16
|
+
)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
from abc import abstractmethod
|
2
|
+
from collections.abc import Callable
|
3
|
+
from typing import TypeVar
|
4
|
+
from typing_extensions import ParamSpec
|
5
|
+
from tqdm import tqdm
|
6
|
+
from navconfig.logging import logging
|
7
|
+
from .credentials import CredentialsInterface
|
8
|
+
|
9
|
+
P = ParamSpec("P")
|
10
|
+
T = TypeVar("T")
|
11
|
+
|
12
|
+
|
13
|
+
class ClientInterface(CredentialsInterface):
|
14
|
+
def __init__(self, *args: P.args, **kwargs: P.kwargs) -> None:
|
15
|
+
super(ClientInterface, self).__init__(*args, **kwargs)
|
16
|
+
# host and port (if needed)
|
17
|
+
self.host: str = kwargs.pop("host", None)
|
18
|
+
if not self.host:
|
19
|
+
self.host = kwargs.pop("hostname", None)
|
20
|
+
self.port: int = kwargs.pop("port", None)
|
21
|
+
self.define_host()
|
22
|
+
self._connection: Callable = None
|
23
|
+
# progress bar
|
24
|
+
self._pb: Callable = None
|
25
|
+
# any other argument
|
26
|
+
self._clientargs = {} # kwargs
|
27
|
+
|
28
|
+
def define_host(self):
|
29
|
+
try:
|
30
|
+
self.host = self.credentials["host"]
|
31
|
+
except KeyError:
|
32
|
+
self.host = self.host
|
33
|
+
try:
|
34
|
+
self.port = self.credentials["port"]
|
35
|
+
except KeyError:
|
36
|
+
self.port = self.port
|
37
|
+
# getting from environment:
|
38
|
+
self.host = self.get_env_value(self.host, default=self.host)
|
39
|
+
self.port = self.get_env_value(str(self.port), default=self.port)
|
40
|
+
if self.host:
|
41
|
+
logging.debug(f"<{__name__}>: HOST: {self.host}, PORT: {self.port}")
|
42
|
+
|
43
|
+
@abstractmethod
|
44
|
+
async def close(self, timeout: int = 5):
|
45
|
+
"""close.
|
46
|
+
Closing the connection.
|
47
|
+
"""
|
48
|
+
|
49
|
+
@abstractmethod
|
50
|
+
async def open(self, credentials: dict, **kwargs):
|
51
|
+
"""open.
|
52
|
+
Starts (open) a connection to an external resource.
|
53
|
+
"""
|
54
|
+
|
55
|
+
async def __aenter__(self) -> "ClientInterface":
|
56
|
+
await self.open(credentials=self.credentials, **self._clientargs)
|
57
|
+
return self
|
58
|
+
|
59
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
|
60
|
+
# clean up anything you need to clean up
|
61
|
+
return await self.close(timeout=1)
|
62
|
+
|
63
|
+
def start_progress(self, total: int = 1):
|
64
|
+
self._pb = tqdm(total=total)
|
65
|
+
|
66
|
+
def close_progress(self):
|
67
|
+
self._pb.close()
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
from typing import TypeVar
|
3
|
+
from typing_extensions import ParamSpec
|
4
|
+
from ....interfaces.mask import MaskSupport
|
5
|
+
|
6
|
+
P = ParamSpec("P")
|
7
|
+
T = TypeVar("T")
|
8
|
+
|
9
|
+
|
10
|
+
class CredentialsInterface(MaskSupport, ABC):
|
11
|
+
def __init__(self, *args: P.args, **kwargs: P.kwargs) -> None:
|
12
|
+
super(CredentialsInterface, self).__init__(*args, **kwargs)
|
13
|
+
self.credentials = self.set_credentials(kwargs.pop("credentials", {}))
|
14
|
+
if not self.credentials:
|
15
|
+
raise ValueError("Missing Credentials on Event Component")
|
16
|
+
|
17
|
+
def set_credentials(self, credentials: dict):
|
18
|
+
for key, default in credentials.items():
|
19
|
+
try:
|
20
|
+
# can process the credentials, extracted from environment or variables:
|
21
|
+
val = self.get_env_value(credentials[key], default=default)
|
22
|
+
if hasattr(self, "mask_replacement"):
|
23
|
+
val = self.mask_replacement(val)
|
24
|
+
credentials[key] = val
|
25
|
+
except (TypeError, KeyError) as ex:
|
26
|
+
self._logger.error(f"{__name__}: Wrong or missing Credentias")
|
27
|
+
raise ValueError(f"{__name__}: Wrong or missing Credentias") from ex
|
28
|
+
return credentials
|
@@ -0,0 +1,58 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
from notify import Notify
|
3
|
+
from notify.providers.email import Email
|
4
|
+
from notify.providers.slack import Slack
|
5
|
+
from notify.providers.teams import Teams
|
6
|
+
from notify.models import Actor, Chat, Channel, TeamsChannel
|
7
|
+
from notify.conf import MS_TEAMS_DEFAULT_TEAMS_ID
|
8
|
+
from flowtask.conf import (
|
9
|
+
EVENT_CHAT_ID,
|
10
|
+
EVENT_CHAT_BOT,
|
11
|
+
DEFAULT_RECIPIENT,
|
12
|
+
EMAIL_USERNAME,
|
13
|
+
EMAIL_PASSWORD,
|
14
|
+
EMAIL_PORT,
|
15
|
+
EMAIL_HOST,
|
16
|
+
SLACK_DEFAULT_CHANNEL,
|
17
|
+
SLACK_DEFAULT_CHANNEL_NAME,
|
18
|
+
MS_TEAMS_NAVIGATOR_CHANNEL,
|
19
|
+
MS_TEAMS_NAVIGATOR_CHANNEL_ID,
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
class Notification(ABC):
|
24
|
+
def get_notify(self, _type, **kwargs):
|
25
|
+
if _type == "telegram":
|
26
|
+
# defining the Default chat object:
|
27
|
+
recipient = Chat(**{"chat_id": EVENT_CHAT_ID, "chat_name": "Navigator"})
|
28
|
+
# send notifications to Telegram bot
|
29
|
+
args = {"bot_token": EVENT_CHAT_BOT, **kwargs}
|
30
|
+
ntf = Notify("telegram", **args)
|
31
|
+
elif _type == "slack":
|
32
|
+
recipient = Channel(
|
33
|
+
channel_id=SLACK_DEFAULT_CHANNEL,
|
34
|
+
channel_name=SLACK_DEFAULT_CHANNEL_NAME,
|
35
|
+
)
|
36
|
+
ntf = Slack()
|
37
|
+
elif _type == "email":
|
38
|
+
account = {
|
39
|
+
"host": EMAIL_HOST,
|
40
|
+
"port": EMAIL_PORT,
|
41
|
+
"username": EMAIL_USERNAME,
|
42
|
+
"password": EMAIL_PASSWORD,
|
43
|
+
**kwargs,
|
44
|
+
}
|
45
|
+
recipient = Actor(**DEFAULT_RECIPIENT)
|
46
|
+
ntf = Email(debug=True, **account)
|
47
|
+
elif _type == "teams":
|
48
|
+
ntf = Teams(as_user=True)
|
49
|
+
recipient = TeamsChannel(
|
50
|
+
name=MS_TEAMS_NAVIGATOR_CHANNEL,
|
51
|
+
team_id=MS_TEAMS_DEFAULT_TEAMS_ID,
|
52
|
+
channel_id=MS_TEAMS_NAVIGATOR_CHANNEL_ID,
|
53
|
+
)
|
54
|
+
else:
|
55
|
+
# Any other Notify Provider:
|
56
|
+
recipient = Actor(**DEFAULT_RECIPIENT)
|
57
|
+
ntf = Notify(_type, **kwargs)
|
58
|
+
return [ntf, recipient]
|
@@ -0,0 +1,122 @@
|
|
1
|
+
import codecs
|
2
|
+
import traceback
|
3
|
+
from jira import JIRA
|
4
|
+
import orjson
|
5
|
+
from ...utils.json import json_encoder
|
6
|
+
from .abstract import AbstractEvent
|
7
|
+
from ...conf import (
|
8
|
+
JIRA_API_TOKEN,
|
9
|
+
JIRA_USERNAME,
|
10
|
+
JIRA_INSTANCE,
|
11
|
+
JIRA_PROJECT
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
class Jira(AbstractEvent):
|
16
|
+
"""Jira.
|
17
|
+
|
18
|
+
Jira Event to create a new Ticket on Error/Exception.
|
19
|
+
"""
|
20
|
+
def __init__(self, *args, **kwargs):
|
21
|
+
super(Jira, self).__init__(*args, **kwargs)
|
22
|
+
self.program = kwargs.pop("program", None)
|
23
|
+
self.task = kwargs.pop("task", None)
|
24
|
+
self.issue_type = kwargs.pop("issue_type", 'Bug')
|
25
|
+
self._status = kwargs.pop("status", "event")
|
26
|
+
self._summary = kwargs.get('summary', 'Error on: ')
|
27
|
+
self._assignee = kwargs.get('assignee', {})
|
28
|
+
# Initialize Jira Connection
|
29
|
+
try:
|
30
|
+
self.jira = JIRA(
|
31
|
+
server=JIRA_INSTANCE,
|
32
|
+
basic_auth=(JIRA_USERNAME, JIRA_API_TOKEN)
|
33
|
+
)
|
34
|
+
except Exception as err:
|
35
|
+
self._logger.error(
|
36
|
+
f"Cannot Connect to Jira {err}"
|
37
|
+
)
|
38
|
+
raise
|
39
|
+
|
40
|
+
async def __call__(self, *args, **kwargs):
|
41
|
+
project_id = kwargs.pop('project_id', JIRA_PROJECT)
|
42
|
+
_message = kwargs.get('message', '')
|
43
|
+
task = kwargs.pop("task", None)
|
44
|
+
status = kwargs.pop("status", "done")
|
45
|
+
program = task.getProgram()
|
46
|
+
task_name = f"{program}.{task.taskname}"
|
47
|
+
error = kwargs.get('error', None)
|
48
|
+
task_id = task.task_id
|
49
|
+
if status not in ("error", "failed", "exception", "task error"):
|
50
|
+
return True
|
51
|
+
# Operar el error
|
52
|
+
try:
|
53
|
+
stat = task.stats # getting the stat object:
|
54
|
+
stats = stat.to_json()
|
55
|
+
except AttributeError:
|
56
|
+
stats = []
|
57
|
+
description = {}
|
58
|
+
if stats:
|
59
|
+
# iterate over task stats:
|
60
|
+
for stat, value in stats["steps"].items():
|
61
|
+
description[stat] = value
|
62
|
+
# Create the Jira Ticket:
|
63
|
+
desc = orjson.dumps(description, option=orjson.OPT_INDENT_2).decode()
|
64
|
+
codereview = codecs.decode(json_encoder(stats['Review']), 'unicode_escape').replace("**", "*")
|
65
|
+
desc = f"""
|
66
|
+
{{code:json}}
|
67
|
+
{desc}
|
68
|
+
{{code}}\n\n
|
69
|
+
"""
|
70
|
+
# Capture the stack trace
|
71
|
+
stack_trace = traceback.format_exc()
|
72
|
+
if stack_trace:
|
73
|
+
desc = f"""
|
74
|
+
{desc}
|
75
|
+
|
76
|
+
h2. *Error*:\n\n
|
77
|
+
{{panel:bgColor=#ffebe6}}\n
|
78
|
+
{error}
|
79
|
+
\n{{panel}}\n\n
|
80
|
+
|
81
|
+
h2. Stack Trace:\n\n
|
82
|
+
{{code:python}}
|
83
|
+
{stack_trace}
|
84
|
+
{{code}}
|
85
|
+
"""
|
86
|
+
args = {
|
87
|
+
'project': project_id,
|
88
|
+
'summary': f"{self._summary} {task_name}",
|
89
|
+
'description': (
|
90
|
+
f"{{color:#FF5630}}[ STATUS: {status.upper()} ]{{color}} \n\n"
|
91
|
+
f"{{panel:bgColor=#deebff}}\n*Task*: {task_name}\n{{panel}}\n\n"
|
92
|
+
f"{{panel:bgColor=#deebff}}\n*Task_id*: {task_id}\n{{panel}}\n\n"
|
93
|
+
f"{{panel:bgColor=#ffebe6}}\n*Message*: {_message}\n{{panel}}\n\n"
|
94
|
+
f"h2. *Task Stats*:\n\n"
|
95
|
+
f"{desc}"
|
96
|
+
f"\n\n----\n\n{{panel:bgColor=#eae6ff}}\nh2. *Code Review*\n\n{codereview}\n\n{{panel}}"
|
97
|
+
),
|
98
|
+
'issuetype': {
|
99
|
+
'name': self.issue_type
|
100
|
+
}
|
101
|
+
}
|
102
|
+
try:
|
103
|
+
new_issue = self.jira.create_issue(**args)
|
104
|
+
self._logger.info(
|
105
|
+
f"Jira Issue Created: {new_issue}"
|
106
|
+
)
|
107
|
+
if self._assignee:
|
108
|
+
try:
|
109
|
+
new_issue.update(
|
110
|
+
assignee=self._assignee
|
111
|
+
)
|
112
|
+
except Exception as err:
|
113
|
+
print('ERROR > ', err)
|
114
|
+
self._logger.warning(
|
115
|
+
f"Error Assigning Jira Issue to {self._assignee}: {err}"
|
116
|
+
)
|
117
|
+
return new_issue
|
118
|
+
except Exception as err:
|
119
|
+
self._logger.error(
|
120
|
+
f"Cannot Create Jira Issue {err}"
|
121
|
+
)
|
122
|
+
raise
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from navconfig import DEBUG
|
2
|
+
from navconfig.logging import logging
|
3
|
+
from .abstract import AbstractEvent
|
4
|
+
|
5
|
+
|
6
|
+
class LogEvent(AbstractEvent):
|
7
|
+
def __init__(self, *args, **kwargs):
|
8
|
+
super(LogEvent, self).__init__(*args, **kwargs)
|
9
|
+
self.use_notice: bool = kwargs.pop("use_notice", False)
|
10
|
+
self._logger = logging.getLogger(
|
11
|
+
"FlowTask.LogEvent"
|
12
|
+
)
|
13
|
+
|
14
|
+
async def __call__(self, *args, **kwargs):
|
15
|
+
msg = kwargs.pop("message", None)
|
16
|
+
cls = kwargs.pop("cls", None)
|
17
|
+
if not msg:
|
18
|
+
msg = getattr(cls, "message", str(cls))
|
19
|
+
if DEBUG:
|
20
|
+
self.echo(msg, level="WARN")
|
21
|
+
self._logger.debug(msg)
|
22
|
+
else:
|
23
|
+
if self.use_notice is True:
|
24
|
+
self._logger.notice(msg)
|
25
|
+
else:
|
26
|
+
self._logger.info(msg)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import socket
|
2
|
+
from datetime import datetime, timezone
|
3
|
+
from redis import asyncio as aioredis
|
4
|
+
from navconfig.logging import logging
|
5
|
+
from ...utils.json import json_encoder
|
6
|
+
from .abstract import AbstractEvent
|
7
|
+
from ...conf import ENVIRONMENT, PUBSUB_REDIS, ERROR_CHANNEL
|
8
|
+
|
9
|
+
|
10
|
+
EVENT_HOST = socket.gethostbyname(socket.gethostname())
|
11
|
+
|
12
|
+
|
13
|
+
class LogError(AbstractEvent):
|
14
|
+
def __init__(self, *args, **kwargs):
|
15
|
+
super(LogError, self).__init__(*args, **kwargs)
|
16
|
+
self._logger = logging.getLogger("FlowTask.LogError")
|
17
|
+
|
18
|
+
async def __call__(self, *args, **kwargs):
|
19
|
+
status = kwargs.pop("status", "event")
|
20
|
+
task = kwargs.pop("task", None)
|
21
|
+
program = task.getProgram()
|
22
|
+
task_name = task.taskname
|
23
|
+
task_id = task.task_id
|
24
|
+
msg = kwargs.pop("message", None)
|
25
|
+
cls = kwargs.pop("cls", None)
|
26
|
+
if not msg:
|
27
|
+
msg = getattr(cls, "message", str(cls))
|
28
|
+
redis = await aioredis.from_url(
|
29
|
+
PUBSUB_REDIS, encoding="utf-8", decode_responses=True
|
30
|
+
)
|
31
|
+
msg = {
|
32
|
+
"task": f"{program}.{task_name}",
|
33
|
+
"task_id": task_id,
|
34
|
+
"type": "error",
|
35
|
+
"status": status,
|
36
|
+
"environment": ENVIRONMENT,
|
37
|
+
"host": EVENT_HOST,
|
38
|
+
"end_time": datetime.now(timezone.utc),
|
39
|
+
}
|
40
|
+
message = json_encoder(msg)
|
41
|
+
try:
|
42
|
+
await redis.publish(ERROR_CHANNEL, message)
|
43
|
+
except Exception as e:
|
44
|
+
self._logger.warning(
|
45
|
+
f"Redis Publisher Error: {e}"
|
46
|
+
)
|
47
|
+
finally:
|
48
|
+
await redis.close()
|
49
|
+
try:
|
50
|
+
await redis.connection_pool.disconnect()
|
51
|
+
except Exception:
|
52
|
+
pass
|
@@ -0,0 +1,59 @@
|
|
1
|
+
from ...interfaces.notification import Notification
|
2
|
+
from ...exceptions import ActionError
|
3
|
+
from .abstract import AbstractEvent
|
4
|
+
|
5
|
+
|
6
|
+
class Notify(Notification, AbstractEvent):
|
7
|
+
async def __call__(self, *args, **kwargs):
|
8
|
+
default_message = self._kwargs.pop("message", None)
|
9
|
+
message = kwargs.pop("message", default_message)
|
10
|
+
# status = kwargs.pop('status', 'event')
|
11
|
+
task = kwargs.pop("task", None)
|
12
|
+
provider, recipient = self.get_notify(**self._kwargs)
|
13
|
+
# Mask transform of message
|
14
|
+
for key, value in self.message.items():
|
15
|
+
self.message[key] = self.mask_replacement(value)
|
16
|
+
## TASK:
|
17
|
+
if self.provider == "email":
|
18
|
+
args = self.get_message(message)
|
19
|
+
if hasattr(self, "with_attachment") and self.with_attachment is True:
|
20
|
+
# check if result are files (build attachments)
|
21
|
+
_vars = task.get_variables()
|
22
|
+
if "FILENAMES" in _vars.keys():
|
23
|
+
result = _vars["FILENAMES"]
|
24
|
+
elif "FILENAME" in _vars.keys():
|
25
|
+
result = _vars["FILENAME"]
|
26
|
+
else:
|
27
|
+
result = kwargs.pop("result", [])
|
28
|
+
self.list_attachment = self.get_attachment_files(result)
|
29
|
+
elif self.provider == "telegram":
|
30
|
+
args = self.get_message(message)
|
31
|
+
if hasattr(self, "with_attachment") and self.with_attachment is True:
|
32
|
+
_vars = task.get_variables()
|
33
|
+
if "FILENAMES" in _vars.keys():
|
34
|
+
result = _vars["FILENAMES"]
|
35
|
+
elif "FILENAME" in _vars.keys():
|
36
|
+
result = _vars["FILENAME"]
|
37
|
+
else:
|
38
|
+
result = kwargs.pop("result", [])
|
39
|
+
self.list_attachment = self.get_attachment_files(result)
|
40
|
+
async with provider as notify:
|
41
|
+
result = await notify.send_document(
|
42
|
+
document=self.list_attachment[0],
|
43
|
+
caption=message,
|
44
|
+
disable_notification=True,
|
45
|
+
)
|
46
|
+
return result
|
47
|
+
else:
|
48
|
+
args = self.get_message(message)
|
49
|
+
if self._template:
|
50
|
+
args["template"] = self._template
|
51
|
+
try:
|
52
|
+
async with provider as notify:
|
53
|
+
args["recipient"] = recipient
|
54
|
+
if self.list_attachment:
|
55
|
+
args["attachments"] = self.list_attachment
|
56
|
+
result = await notify.send(**args)
|
57
|
+
self._logger.debug(f"Notification Status: {result}")
|
58
|
+
except Exception as err:
|
59
|
+
raise ActionError(f"Error Creating Notification App: {err}") from err
|