DEV Community

Cover image for Como identificar se a automação está executando localmente ou no BotCity Orquestrador?
Morganna for BotCity

Posted on

Como identificar se a automação está executando localmente ou no BotCity Orquestrador?

A dúvida surgiu

Enquanto estávamos em nossa live coding desenvolvendo uma automação com Python e fazendo integração com e-mail e Google Sheets, surgiu uma dúvida:

Como identificar se a automação está executando localmente ou no BotCity Orquestrador?

Essa dúvida surgiu por causa da seguinte situação: quando estamos executando nossa automação localmente, ou seja, em nosso computador ou máquina virtual, e queremos conectá-la com o BotCity Orquestrador, precisamos utilizar o BotCity Maestro SDK para fazer login na plataforma. Mas quando fazemos deploy no Orquestrador, esse trecho de código para o login não precisa existir.

Exemplo prático

Criei um robô seguindo a documentação do framework web para exemplo. Abaixo temos o código principal:

# Import for the Web Bot
from botcity.web import WebBot, Browser, By

# Import for integration with BotCity Maestro SDK
from botcity.maestro import *

# Disable errors if we are not connected to Maestro
BotMaestroSDK.RAISE_NOT_CONNECTED = False


def main():
    # Runner passes the server url, the id of the task being executed,
    # the access token and the parameters that this task receives (when applicable).
    maestro = BotMaestroSDK.from_sys_args()
    ## Fetch the BotExecution with details from the task, including parameters
    execution = maestro.get_execution()

    print(f"Task ID is: {execution.task_id}")
    print(f"Task Parameters are: {execution.parameters}")

    bot = WebBot()

    # Configure whether or not to run on headless mode
    bot.headless = False

    # Uncomment to change the default Browser to Firefox
    # bot.browser = Browser.FIREFOX

    # Uncomment to set the WebDriver path
    # bot.driver_path = "<path to your WebDriver binary>"

    # Opens the BotCity website.
    bot.browse("https://www.botcity.dev")

    # Implement here your logic...
    ...

    # Wait 3 seconds before closing
    bot.wait(3000)

    # Finish and clean up the Web Browser
    # You MUST invoke the stop_browser to avoid
    # leaving instances of the webdriver open
    bot.stop_browser()

    # Uncomment to mark this task as finished on BotMaestro
    # maestro.finish_task(
    #     task_id=execution.task_id,
    #     status=AutomationTaskFinishStatus.SUCCESS,
    #     message="Task Finished OK."
    # )


def not_found(label):
    print(f"Element not found: {label}")


if __name__ == '__main__':
    main()
Enter fullscreen mode Exit fullscreen mode

E assim fica o código do requirements.txt:

botcity-framework-web>=0.8.0,<1.0
botcity-maestro-sdk>=0.3.3,<1.0
Enter fullscreen mode Exit fullscreen mode

O que eu fiz para poder executar esse código, foi descomentar a linha:

bot.browser = Browser.FIREFOX
Enter fullscreen mode Exit fullscreen mode

E adicionar o geckodriver na configuração do WebDriver, deixando-o na pasta resources:

bot.driver_path = r"resources\geckodriver.exe"
Enter fullscreen mode Exit fullscreen mode

Esse bot é apenas um exemplo e o que ele faz ao ser executado é abrir o navegador Firefox (poderia ter sido o Chrome, Edge, entre outros) com o site da BotCity e, depois de três segundos, fecha o navegador.

Conexão com BotCity Orquestrador

Se você precisar se conectar com a plataforma para orquestração, você precisará adicionar o seguinte código para fazer login no BotCity Orquestrador:

maestro.login(
    server='MAESTRO_SERVER', 
    login='MAESTRO_LOGIN', 
    key='MAESTRO_KEY'
)
Enter fullscreen mode Exit fullscreen mode

Por serem dados sensíveis, uma saída para ocultar os dados é utilizando dotenv do Python e o OS. Para isso, basta importar da seguinte forma:

from dotenv import load_dotenv
import os

...

def main():
    load_dotenv()
    ...
Enter fullscreen mode Exit fullscreen mode

E no arquivo requirements.txt precisa adicionar a biblioteca dotenv:

botcity-framework-web>=0.8.0,<1.0
botcity-maestro-sdk>=0.3.3,<1.0

python-dotenv
Enter fullscreen mode Exit fullscreen mode

Além disso também é necessário termos um arquivo chamado .env, pois é de lá que o código buscará as informações. E esse arquivo ficará da seguinte forma:

MAESTRO_SERVER = "coloque o server aqui"
MAESTRO_LOGIN = "coloque o login aqui"
MAESTRO_KEY = "coloque a key aqui"
Enter fullscreen mode Exit fullscreen mode

Essas informações ficam disponíveis em Dev. Environment, no BotCity Orquestrador.

OBS: É importante lembrar de não disponibilizar o .env ao versionar em plataformas como o GitHub, Gitlab, entre outras. Para facilitar, adicione .env ao arquivo .gitignore.

Qual a diferença entre o ambiente local e o orquestrador

Quando executamos nossa automação dentro do Orquestrador, uma tarefa é criada, atrelada a automação que fizemos o deploy, então por ele nós temos o ID da tarefa (ou task_id). Já no ambiente local, não temos essa informação.

Como validar em qual ambiente está sendo executado

Então podemos, por exemplo, fazer a seguinte validação: se task_id for igual a 0, estamos executando localmente e precisamos fazer o processo de login com o Orquestrador. Caso contrário, o task_id existe e, então, não precisamos fazer o login.

...
    maestro = BotMaestroSDK.from_sys_args()

    ## Fetch the BotExecution with details from the task, including parameters
    execution = maestro.get_execution()

    if(execution.task_id == 0):
        print("Running locally so we need to login to BotCity Orchestrator.")
        maestro.login(
            server=os.getenv('MAESTRO_SERVER'), 
            login=os.getenv('MAESTRO_LOGIN'), 
            key=os.getenv('MAESTRO_KEY')
        )
    else:
        print("Running with BotCity Orchestrator.")
...
Enter fullscreen mode Exit fullscreen mode

Execução local

Ao testar a execução do robô localmente, percebemos que retorna a mensagem correta no terminal:

print do terminal do Visual Studio Code com foco na mensagem

Execução no Orquestrador

Ao testar a execução do robô no Orquestrador, percebemos que retorna a mensagem correta no terminal:

print do log do Runner com foco na mensagem

Código completo

Caso queira validar como ficou o código principal completo, segue abaixo:

# Import for the Web Bot
from botcity.web import WebBot, Browser, By

# Import for integration with BotCity Maestro SDK
from botcity.maestro import *

from dotenv import load_dotenv
import os

# Disable errors if we are not connected to Maestro
BotMaestroSDK.RAISE_NOT_CONNECTED = False


def main():
    load_dotenv()

    # Runner passes the server url, the id of the task being executed,
    # the access token and the parameters that this task receives (when applicable).
    maestro = BotMaestroSDK.from_sys_args()

    ## Fetch the BotExecution with details from the task, including parameters
    execution = maestro.get_execution()

    if(execution.task_id == 0):
        print("Running locally so we need to login to BotCity Orchestrator.")
        maestro.login(
            server=os.getenv('MAESTRO_SERVER'), 
            login=os.getenv('MAESTRO_LOGIN'), 
            key=os.getenv('MAESTRO_KEY')
        )
    else:
        print("Running with BotCity Orchestrator.")

    bot = WebBot()

    # Configure whether or not to run on headless mode
    bot.headless = False

    # Uncomment to change the default Browser to Firefox
    bot.browser = Browser.FIREFOX

    # Uncomment to set the WebDriver path
    bot.driver_path = r"resources\geckodriver.exe"

    # Opens the BotCity website.
    bot.browse("https://www.botcity.dev")

    # Implement here your logic...
    ...

    # Wait 3 seconds before closing
    bot.wait(3000)

    # Finish and clean up the Web Browser
    # You MUST invoke the stop_browser to avoid
    # leaving instances of the webdriver open
    bot.stop_browser()

    # Uncomment to mark this task as finished on BotMaestro
    maestro.finish_task(
        task_id=execution.task_id,
        status=AutomationTaskFinishStatus.SUCCESS,
        message="Task Finished OK."
    )


def not_found(label):
    print(f"Element not found: {label}")


if __name__ == '__main__':
    main()
Enter fullscreen mode Exit fullscreen mode

O que achou?

Espero que tenha curtido a dica e possa adaptá-la de acordo com a necessidade da sua execução. Qualquer dúvida, basta entrar em contato pela nossa comunidade.

Top comments (1)

Collapse
 
eduardoklosowski profile image
Eduardo Klosowski • Edited

Eu também gosto como algumas soluções de CI fazem para identificar quando algo está executando nelas, no caso criando uma variável de ambiente chamada CI, por exemplo, se ela existir sabe-se que está rodando dentro do CI, se não, sabe-se que é local. O que poderia ser adaptado com a ideia do .env, e está de acordo com a seção de configuração do 12 factor app.

Outra coisa que poderia ser interessante trabalhar nesse caso é a injeção de dependência, onde tem uma classe que faz o login e outra fake, e dependendo da onde está rodando o programa injetar uma classe ou outra.