Provedor de recursos Pulumi Databricks

Observação

Este artigo abrange o Pulumi, que não é fornecido nem suportado pelo Databricks. Para entrar em contato com o provedor, consulte Suporte Pulumi.

Este artigo mostra como usar Python e Pulumi, uma plataforma terceirizada de infraestrutura como código (IaC) que permite criar, aprimorar e gerenciar recursos do Databricks usando linguagens de programação, ferramentas e práticas de engenharia familiares. Embora este artigo mostre como usar o Python e o provedor de recursos Pulumi Databricks, o Pulumi oferece suporte a outras linguagens além do Python para Databricks, incluindo TypeScript, JavaScript, Go e C#.

O provedor de recursos Pulumi Databricks é baseado no provedor Databricks Terraform. Para obter mais informações, consulte Terraform Cloud.

Requisitos

Os passos a seguir mostram como criar um projeto Pulumi Databricks com Python. Em vez disso, para obter um tutorial de uma perspectiva puramente do provedor cloud , consulte Comece a usar a AWS na documentação do Pulumi. Para obter um tutorial de uma perspectiva de linguagem de programação em primeiro lugar, consulte Python, Node.js (JavaScript, TypeScript), Go e .NET (C#, VB, F#) na documentação do Pulumi.

Passo 1: Criar um projeto Pulumi

Nesta passo, em sua máquina de desenvolvimento local, você configura a estrutura de diretórios necessária para um projeto Pulumi. Em seguida, você cria seu projeto Pulumi dentro dessa estrutura de diretório.

  1. No seu terminal ou com o PowerShell, crie um diretório vazio e alterne para ele, por exemplo:

    mkdir pulumi-demo
    cd pulumi-demo
    
    md pulumi-demo
    cd pulumi-demo
    
  2. Instale o Pulumi executando o seguinte comando, dependendo do seu sistema operacional:

    Instale o Pulumi no Unix ou Linux usando curl:

    curl -fsSL https://get.pulumi.com | sh
    

    Instale o Pulumi no macOS usando o Homebrew:

    brew install pulumi/tap/pulumi
    

    Instale o Pulumi no Windows usando o PowerShell com permissões elevadas por meio do gerenciador de pacotes Chocolatey:

    choco install pulumi
    

    Para opções alternativas de instalação do Pulumi, consulte downloads e instalação na documentação do Pulumi.

  3. Crie um projeto Python Pulumi básico executando o seguinte comando:

    pulumi new python
    

    Dica

    Você também pode criar um projeto Pulumi a partir de sua account Pulumi online (Projetos > Criar projeto). No entanto, não há nenhum projeto padrão para Databricks.

  4. Se solicitado, pressione a key Enter e use o navegador da Web para fazer login na sua account Pulumi online, caso ainda não esteja conectado. Depois de entrar, retorne ao seu terminal ou PowerShell.

  5. Quando for solicitado um nome de projeto, aceite o nome de projeto default de pulumi-demo pressionando Enter.

  6. Quando solicitado a fornecer uma descrição do projeto, insira A demo Python Pulumi Databricks project e pressione Enter.

  7. quando for solicitado um nome de pilha, aceite o nome de pilha default de dev pressionando Enter. Pulumi cria os seguintes arquivos e subdiretório em seu diretório pulumi-demo :

    • Pulumi.yaml, que é uma lista de configurações para seu projeto Pulumi.

    • __main__.py, que contém o código Python que você escreve para seu projeto Pulumi.

    • requirements.txt, que é uma lista de pacotes de código Python de suporte que o Pulumi instala para o seu projeto.

    • .gitignore, que é uma lista de arquivos e diretórios que o Git ignora se você quiser enviar este projeto para um repositório Git remoto.

    • O subdiretório venv contém código de ambiente virtual Python compatível que Pulumi usa para seu projeto.

  8. Execute uma implantação inicial da pilha dev do seu projeto executando o seguinte comando:

    pulumi up
    
  9. Quando solicitado a executar esta atualização, pressione a key de seta para cima para navegar até sim e pressione Enter.

  10. Copie o link view ao vivo que aparece e cole-o na barra de endereço do navegador da web, que o levará à sua account Pulumi online. Os detalhes da atividade da pilha dev para seu projeto pulumi-demo são exibidos. Não há muito o que ver agora, porque ainda não há recursos em sua pilha. Você cria esses recursos na próxima passo.

Passo 2: Criar recursos do Databricks

Nesta passo, você usa o provedor de recursos Pulumi Databricks para criar, em seu workspace Databricks existente, um Notebook e um Job para executar esse Notebook.

  1. No arquivo __main.py__ que Pulumi gerou, use seu editor de texto preferido ou ambiente de desenvolvimento integrado (IDE) para inserir o código a seguir. Este código declara os recursos Pulumi Databricks Notebook e Job e suas configurações:

    """A Python Pulumi program"""
    
    import pulumi
    from pulumi_databricks import *
    from base64 import b64encode
    
    # Get the authenticated user's workspace home directory path and email address.
    # See https://www.pulumi.com/registry/packages/databricks/api-docs/getcurrentuser
    user_home_path     = get_current_user().home
    user_email_address = get_current_user().user_name
    
    # Define the name prefix to prepend to the resource names that are created
    # for the Notebook and Job resources. To do this, you can use a Pulumi
    # configuration value instead of hard-coding the name prefix in this file.
    #
    # To set a Pulumi configuration value, run the following command, which sets
    # a "resource-prefix" configuration value to "pulumi-demo" in the
    # associated "Pulumi.<stack-name>.yaml" configuration file:
    #
    # pulumi config set resource-prefix "pulumi-demo"
    #
    # For more information about defining and retrieving hard-coded values, see
    # https://www.pulumi.com/docs/intro/concepts/config
    config = pulumi.config.Config()
    resource_prefix = config.require('resource-prefix')
    
    # Define cluster resource settings.
    node_type = config.require('node-type')
    
    # Create a Notebook resource.
    # See https://www.pulumi.com/registry/packages/databricks/api-docs/notebook
    # This example adds a single cell to the notebook, which is constructed from
    # a single base64-encoded string. In practice, you would replace this:
    #
    # language       = "PYTHON",
    # content_base64 = b64encode(b"display(spark.range(10))").decode("UTF-8")
    #
    # With this:
    #
    # source         = "path/to/local/my-notebook.py"
    #
    # To provide more notebook content easier and faster. Also, the notebook's language
    # is automatically detected. If you specify a notebook path, be sure that it does
    # not end in .ipynb, as Pulumi relies on the workspace import API, which doesn't
    # rely on any specific extensions such as .ipynb in the notebook path.
    notebook = Notebook(
      resource_name  = f"{resource_prefix}-notebook",
      path           = f"{user_home_path}/Pulumi/{resource_prefix}-notebook.py",
      language       = 'PYTHON',
      content_base64 = b64encode(b"display(spark.range(10))").decode("UTF-8")
    )
    
    # Export the URL of the Notebook, so that you can easily browse to it later.
    # See https://www.pulumi.com/docs/intro/concepts/stack/#outputs
    pulumi.export('Notebook URL', notebook.url)
    
    # Create a Job resource.
    # See https://www.pulumi.com/registry/packages/databricks/api-docs/job
    # This job uses the most recent Databricks Runtime long-term support (LTS)
    # runtime programmatic version ID at the time this article was first published,
    # which is 14.3.x-scala2.12. You can replace this with a later version.
    job = Job(
      resource_name = f"{resource_prefix}-job",
      name = f"{resource_prefix}-job",
      tasks = [
        JobTaskArgs(
          task_key = f"{resource_prefix}-task",
          new_cluster   = JobNewClusterArgs(
            num_workers   = 1,
            spark_version = "14.3.x-scala2.12",
            node_type_id  = node_type
          ),
          notebook_task = JobNotebookTaskArgs(
            notebook_path = f"{user_home_path}/Pulumi/{resource_prefix}-notebook.py"
          )
        )
      ],
      email_notifications = JobEmailNotificationsArgs(
        on_successes = [ user_email_address ],
        on_failures  = [ user_email_address ]
      )
    )
    
    # Export the URL of the Job, so that you can easily browse to it later.
    # See https://www.pulumi.com/docs/intro/concepts/stack/#outputs
    pulumi.export('Job URL', job.url)
    
  2. Defina um valor de configuração denominado resource-prefix e defina-o como o valor embutido em código pulumi-demo, executando o seguinte comando. Pulumi usa este valor de configuração para nomear o Notebook e Job:

    pulumi config set resource-prefix "pulumi-demo"
    

    Pulumi cria um arquivo denominado Pulumi.dev.yaml no mesmo diretório que o arquivo __main__.py e adiciona o seguinte código a este arquivo YAML:

    config:
      pulumi-demo:resource_prefix: pulumi-demo
    

    O uso de valores de configuração permite que seu código seja mais modular e reutilizável. Agora outra pessoa pode reutilizar seu arquivo __main__.py e definir um valor diferente para a variável resource_prefix sem alterar o conteúdo do arquivo __main__.py .

  3. Defina um valor de configuração denominado node-type e defina-o com o seguinte valor embutido em código, executando o seguinte comando. Pulumi usa esse valor de configuração para determinar o tipo de clusters em que a execução do Job .

    pulumi config set node-type "i3.xlarge"
    

    O conteúdo do arquivo Pulumi.dev.yaml agora se parece com isto:

    config:
      pulumi-demo:node-type: i3.xlarge
      pulumi-demo:resource-prefix: pulumi-demo
    
  4. Para permitir que Pulumi se autentique com seu workspace do Databricks, defina valores de configuração específicos do Databricks executando o comando relacionado. Por exemplo, para autenticação access token pessoal do Databricks, execute o seguinte comando. Nestes comandos:

    • Substitua <workspace-instance-url> pelo URL da instância do espaço de trabalho, por exemplo, https://dbc-a1b2345c-d6e7.cloud.databricks.com.

    • Substitua <access-token> pelo valor de seus access tokens . Certifique-se de especificar a opção --secret . Isso instrui Pulumi a criptografar seus access tokens como uma prática recomendada de segurança.

      Observação

      Por default, o Pulumi usa uma key de criptografia por pilha gerenciada pelo serviço Pulumi, e um sal por valor, para criptografar valores. Para usar um provedor de criptografia alternativo, consulte Configurando a criptografia de segredos na documentação do Pulumi.

    pulumi config set databricks:host "<workspace-instance-url>"
    pulumi config set databricks:token "<access-token>" --secret
    

    O conteúdo do arquivo Pulumi.dev.yaml agora se parece com isto:

    config:
      databricks:host: <your-workspace-instance-url>
      databricks:token:
        secure: <an-encrypted-version-of-your-access-token>
      pulumi-demo:node-type: i3.xlarge
      pulumi-demo:resource_prefix: pulumi-demo
    

    Para usar um tipo de autenticação diferente do Databricks, consulte os Requisitos. Consulte também Configuração nos repositórios Pulumi Databricks no GitHub.

Passo 3: Aprimorar os recursos

Nesta passo, você ativa um ambiente virtual Python que Pulumi fornece para seu projeto como parte da execução do projeto Pulumi Python padrão. Esse ambiente virtual ajuda a garantir que você esteja usando a versão correta do Python, Pulumi e o provedor de recursos Pulumi Databricks juntos. Existem várias estruturas de ambiente virtual Python disponíveis, como venv, virtualenv e pipenv. Este artigo e o projeto Pulumi Python padrão usam venv. venv já está incluído no Python. Para obter mais informações, consulte Criando ambientes virtuais.

  1. Ative o ambiente virtual Python executando o seguinte comando no diretório pulumi-demo , dependendo do sistema operacional e do tipo de shell:

    Plataforma

    shell

    comando para ativar ambiente virtual

    Unix, Linux, MacOS

    bash/zsh

    source venv/bin/activate

    peixe

    source venv/bin/activate.fish

    csh/tcsh

    source venv/bin/activate.csh

    Núcleo do PowerShell

    venv/bin/Activate.ps1

    janelas

    cmd.exe

    venv\Scripts\activate.bat

    PowerShell

    venv\Scripts\Activate.ps1

  2. Instale o provedor de recursos Pulumi Databricks do Python pacote Index (PyPI) em seu ambiente virtual executando o seguinte comando:

    pip install pulumi-databricks
    

    Observação

    Algumas instalações de pip podem exigir que você use pip3 em vez de pip. Em caso afirmativo, substitua pip por pip3 ao longo destes artigos.

  3. Visualize os recursos que o Pulumi criará executando o seguinte comando:

    pulumi preview
    

    Se houver erros relatados, corrija-os e execute o comando novamente.

    Para view um relatório detalhado em sua account Pulumi on-line sobre o que Pulumi fará, copie o link de view ao vivo que aparece e cole-o na barra de endereços do navegador da web.

  4. Crie e aprimore os recursos para seu workspace Databricks executando o seguinte comando:

    pulumi up
    
  5. Quando solicitado a executar esta atualização, pressione a key de seta para cima para navegar até sim e pressione Enter. Se houver erros relatados, corrija-os e execute o comando novamente.

  6. Para view um relatório detalhado em sua account Pulumi on-line sobre o que Pulumi fez, copie o link view ao vivo que aparece e cole-o na barra de endereços do navegador da web.

Passo 4: Interagir com os recursos

Nesta passo, você executa o Job em seu workspace do Databricks, que executa o Notebook especificado.

  1. Para view o Notebook que o Job executará em seu workspace, copie o link da URLNotebook que aparece e cole-o na barra de endereços do seu navegador.

  2. Para view o Job que executa o Notebook em seu workspace, copie o link URLJob que aparece e cole-o na barra de endereços do seu navegador.

  3. Para executar o Job, clique no botão Execution Now na página Job .

  4. Depois que a execução do Job terminar, para view os resultados da execução do Job , na lista Execuções concluídas (últimos 60 dias) na página Job , clique na entrada de tempo mais recente na coluna de horário de início . O painel Output mostra o resultado da execução do código do Notebook , que imprime os números de 1 a 10.

(Opcional) Passo 5: Fazer alterações em um recurso

Nesta passo opcional, você altera o código do Notebook, reimplementa o Notebook alterado e, em seguida, usa o Job para executar novamente o Notebook alterado.

Caso não queira fazer nenhuma alteração no Notebook, pule para o passo 6: Limpar.

  1. De volta ao arquivo __main.py__ , altere esta linha de código:

    content_base64 = b64encode(b"display(spark.range(10))").decode("UTF-8")
    

    Para isso, e salve o arquivo:

      content_base64 = b64encode(b'''
    data = [
             { "Category": 'A', "ID": 1, "Value": 121.44 },
             { "Category": 'B', "ID": 2, "Value": 300.01 },
             { "Category": 'C', "ID": 3, "Value": 10.99 },
             { "Category": 'E', "ID": 4, "Value": 33.87}
           ]
    
    df = spark.createDataFrame(data)
    
    display(df)
    ''').decode("UTF-8")
    

    Essa alteração instrui o Notebook a imprimir o conteúdo do DataFrame especificado em vez dos números de 1 a 10.

    Observação

    Certifique-se de que as linhas de código que começam com data e terminam com ''').decode("UTF-8") estejam alinhadas com a borda do editor de código. Caso contrário, o Pulumi inserirá espaços em branco adicionais no Notebook, o que pode fazer com que o novo código Python falhe na execução.

  2. Opcionalmente, visualize o recurso que o Pulumi alterará executando o seguinte comando:

    pulumi preview
    

    Se houver erros relatados, corrija-os e execute o comando novamente.

    Para view um relatório detalhado em sua account Pulumi on-line sobre o que Pulumi fará, copie o link de view ao vivo que aparece e cole-o na barra de endereços do navegador da web.

  3. aprimore a alteração de recurso em seu workspace do Databricks executando o seguinte comando:

    pulumi up
    
  4. Quando solicitado a executar esta atualização, pressione a key de seta para cima para navegar até sim e pressione Enter. Se houver erros relatados, corrija-os e execute o comando novamente.

  5. Para view um relatório detalhado em sua account Pulumi on-line sobre o que Pulumi fez, copie o link view ao vivo que aparece e cole-o na barra de endereços do navegador da web.

  6. Para view o Notebook alterado em seu workspace, copie o link da URLNotebook que aparece e cole-o na barra de endereços do seu navegador.

  7. Para reexecutar o Job com o Notebook alterado, copie o link URLJob que aparece e cole-o na barra de endereços do seu navegador. Em seguida, clique no botão executar agora na página Job .

  8. Depois que a execução do Job terminar, para view os resultados da execução do Job , na lista Execuções concluídas (últimos 60 dias) na página Job , clique na entrada de tempo mais recente na coluna de horário de início . O painel Output mostra o resultado da execução do código do Notebook , que imprime o conteúdo do DataFrame especificado.

Passo 6: Limpar

Nesta passo, você instrui Pulumi a remover o Notebook e Job de seu workspace Databricks, bem como remover o projeto pulumi-demo e sua pilha dev de sua account Pulumi online.

  1. Remova os recursos do workspace do Databricks executando o seguinte comando:

    pulumi destroy
    
  2. Quando solicitado a executar essa remoção, pressione a key de seta para cima para navegar até sim e pressione Enter.

  3. Remova o projeto Pulumi pulumi-demo e sua pilha dev de sua account Pulumi on-line executando o seguinte comando:

    pulumi stack rm dev
    
  4. Quando solicitado a executar esta remoção, digite dev e pressione Enter.

  5. Para desativar o ambiente virtual Python venv , execute o seguinte comando:

    deactivate
    

Testes

O senhor pode testar seu projeto Pulumi antes de implantá-lo. Consulte Testando programas do Pulumi na documentação do Pulumi.

Para testes de unidade de Pythonprojetos Pulumi baseados em , o senhor pode escrever e executar testes de unidade usando Python a estrutura de teste unittest do junto com o namespace pulumi.runtime do pacote Pulumi. Para executar testes com recurso simulado, o senhor substitui as chamadas para o Pulumi (e para Databricks) por mocks. Consulte Teste de unidade dos programas do Pulumi na documentação do Pulumi.

O arquivo de exemplo a seguir, denominado infra.py, simula uma implementação dos sites Notebook e Job declarados no arquivo main.py deste artigo. Os testes de unidade neste exemplo verificam se o conteúdo codificado em Base64 do Notebook, o nome do Jobe o destinatário do email para a execução bem-sucedida do Job retornam os valores esperados. Dessa forma, somente essas propriedades relacionadas são simuladas aqui com valores de exemplo. Além disso, os valores de propriedade de recurso necessários sempre devem ser fornecidos, mesmo que o senhor não planeje usá-los em seus testes de unidade. Neste exemplo, esses valores obrigatórios são definidos como valores my-mock- aleatórios, e esses valores não são testados.

# infra.py

from pulumi_databricks import (
  Notebook,
  Job,
  JobEmailNotificationsArgs
)

notebook = Notebook(
  resource_name  = 'my-mock-notebook-resource-name',
  path           = 'my-mock-notebook-path',
  content_base64 = 'ZGlzcGxheShzcGFyay5yYW5nZSgxMCkp'
)

job = Job(
  resource_name = 'my-mock-job-resource-name',
  name          = 'pulumi-demo-job',
  email_notifications = JobEmailNotificationsArgs(
    on_successes = [ 'someone@example.com' ]
  )
)

O arquivo de exemplo test_main.py a seguir testa se as propriedades relacionadas retornam os valores esperados.

# test_main.py

import pulumi
from pulumi_databricks import *
import unittest
import infra

# Set up mocking.
class MyMocks(pulumi.runtime.Mocks):
  def new_resource(self, type_, name, inputs, provider, id_):
    return [name + '_id', inputs]

  def call(self, token, args, provider):
    return {}

pulumi.runtime.set_mocks(MyMocks())

class TestNotebookAndJob(unittest.TestCase):
  @pulumi.runtime.test
  def test_notebook(self):
    def check_notebook_content_base64(args):
      content_base64 = args
      # Does the notebook's Base64-encoded content match the expected value?
      self.assertIn('ZGlzcGxheShzcGFyay5yYW5nZSgxMCkp', content_base64)

    # Pass the mocked notebook's content_base64 property value to the test.
    return pulumi.Output.all(infra.notebook.content_base64).apply(check_notebook_content_base64)

  @pulumi.runtime.test
  def test_job(self):
    def check_job_name_and_email_onsuccesses(args):
      name, email_notifications = args
      # Does the job's name match the expected value?
      self.assertIn('pulumi-demo-job', name)
      # Does the email address for successful job runs match the expected value?
      self.assertIn('someone@example.com', email_notifications['on_successes'])

    # Pass into the test the mocked job's property values for the job's name
    # and the job's email address for successful runs.
    return pulumi.Output.all(
      infra.job.name,
      infra.job.email_notifications
    ).apply(check_job_name_and_email_onsuccesses)

Para executar esses testes e exibir seus resultados, execute o seguinte comando no diretório raiz do projeto Pulumi:

python -m unittest

Para obter informações sobre outros tipos de testes que o senhor pode executar, consulte os artigos a seguir na documentação do Pulumi: