”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Implementando uma Lambda com GitLab CI/CD e Terraform para Integração SFTP, S Databricks em Go

Implementando uma Lambda com GitLab CI/CD e Terraform para Integração SFTP, S Databricks em Go

发布于2024-11-08
浏览:805

Implementando uma Lambda com GitLab CI/CD e Terraform para Integração SFTP, S Databricks em Go

Reduzindo Custos com Automação de Processos no Databricks

Tive uma necessidade em um cliente de reduzir o custo de processos que rodavam no Databricks. Uma das features que o Databricks era responsável era de coletar os arquivos de vários SFTP, descompactá-los e colocá-los no Data Lake.

A automação de fluxos de trabalho de dados é um componente crucial na engenharia de dados moderna. Neste artigo, exploraremos como criar uma função AWS Lambda usando GitLab CI/CD e Terraform, que permite a uma aplicação em Go conectar-se a um servidor SFTP, coletar arquivos, armazená-los no Amazon S3 e, por fim, acionar um job no Databricks. Este processo end-to-end é essencial para sistemas que dependem de integração e automação de dados eficientes.

O que Você Vai Precisar para Este Artigo

  • Conta no GitLab com um repositório para o projeto.
  • Conta na AWS com permissões para criar recursos Lambda, S3 e IAM.
  • Conta no Databricks com permissões para criar e executar jobs.
  • Conhecimento básico em Go, Terraform e GitLab CI/CD.

Passo 1: Preparando a Aplicação em Go

Comece criando uma aplicação em Go que se conectará ao servidor SFTP para coletar arquivos. Utilize pacotes como github.com/pkg/sftp para estabelecer a conexão SFTP e github.com/aws/aws-sdk-go para interagir com o serviço S3 da AWS.

package main

import (
 "fmt"
 "log"
 "os"
 "path/filepath"

 "github.com/pkg/sftp"
 "golang.org/x/crypto/ssh"
 "github.com/aws/aws-sdk-go/aws"
 "github.com/aws/aws-sdk-go/aws/session"
 "github.com/aws/aws-sdk-go/service/s3/s3manager"
)

func main() {
 // Configuração do cliente SFTP
 user := "seu_usuario_sftp"
 pass := "sua_senha_sftp"
 host := "endereco_sftp:22"
 config := &ssh.ClientConfig{
  User: user,
  Auth: []ssh.AuthMethod{
   ssh.Password(pass),
  },
  HostKeyCallback: ssh.InsecureIgnoreHostKey(),
 }

 // Conectar ao servidor SFTP
 conn, err := ssh.Dial("tcp", host, config)
 if err != nil {
  log.Fatal(err)
 }
 client, err := sftp.NewClient(conn)
 if err != nil {
  log.Fatal(err)
 }
 defer client.Close()

 // Baixar arquivos do SFTP
 remoteFilePath := "/path/to/remote/file"
 localDir := "/path/to/local/dir"
 localFilePath := filepath.Join(localDir, filepath.Base(remoteFilePath))
 dstFile, err := os.Create(localFilePath)
 if err != nil {
  log.Fatal(err)
 }
 defer dstFile.Close()

 srcFile, err := client.Open(remoteFilePath)
 if err != nil {
  log.Fatal(err)
 }
 defer srcFile.Close()

 if _, err := srcFile.WriteTo(dstFile); err != nil {
  log.Fatal(err)
 }

 fmt.Println("Arquivo baixado com sucesso:", localFilePath)

 // Configuração do cliente S3
 sess := session.Must(session.NewSession(&aws.Config{
  Region: aws.String("us-west-2"),
 }))
 uploader := s3manager.NewUploader(sess)

 // Carregar arquivo para o S3
 file, err := os.Open(localFilePath)
 if err != nil {
  log.Fatal(err)
 }
 defer file.Close()

 _, err = uploader.Upload(&s3manager.UploadInput{
  Bucket: aws.String("seu-bucket-s3"),
  Key:    aws.String(filepath.Base(localFilePath)),
  Body:   file,
 })
 if err != nil {
  log.Fatal("Falha ao carregar arquivo para o S3:", err)
 }

 fmt.Println("Arquivo carregado com sucesso no S3")
}

Passo 2: Configurando o Terraform

O Terraform será usado para provisionar a função Lambda e os recursos necessários na AWS. Crie um arquivo main.tf com a configuração necessária para criar a função Lambda, as políticas de IAM e os buckets do S3.

provider "aws" {
  region = "us-east-1"
}

resource "aws_iam_role" "lambda_execution_role" {
  name = "lambda_execution_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = "sts:AssumeRole",
        Effect = "Allow",
        Principal = {
          Service = "lambda.amazonaws.com"
        },
      },
    ]
  })
}

resource "aws_iam_policy" "lambda_policy" {
  name        = "lambda_policy"
  description = "A policy that allows a lambda function to access S3 and SFTP resources"

  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = [
          "s3:ListBucket",
          "s3:GetObject",
          "s3:PutObject",
        ],
        Effect = "Allow",
        Resource = [
          "arn:aws:s3:::seu-bucket-s3",
          "arn:aws:s3:::seu-bucket-s3/*",
        ],
      },
    ]
  })
}

resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
  role       = aws_iam_role.lambda_execution_role.name
  policy_arn = aws_iam_policy.lambda_policy.arn
}

resource "aws_lambda_function" "sftp_lambda" {
  function_name = "sftp_lambda_function"

  s3_bucket = "seu-bucket-s3-com-codigo-lambda"
  s3_key    = "sftp-lambda.zip"

  handler = "main"
  runtime = "go1.x"

  role = aws_iam_role.lambda_execution_role.arn

  environment {
    variables = {
      SFTP_HOST     = "endereco_sftp",
      SFTP_USER     = "seu_usuario_sftp",
      SFTP_PASSWORD = "sua_senha_sftp",
      S3_BUCKET     = "seu-bucket-s3",
    }
  }
}

resource "aws_s3_bucket" "s3_bucket" {
  bucket = "seu-bucket-s3"
  acl    = "private"
}

Passo 3: Configurando o GitLab CI/CD

No GitLab, defina o pipeline CI/CD no arquivo .gitlab-ci.yml. Este pipeline deve incluir etapas para testar a aplicação Go, executar o Terraform para provisionar a infraestrutura e uma etapa para limpeza, se necessário.

stages:
  - test
  - build
  - deploy

variables:
  S3_BUCKET: "seu-bucket-s3"
  AWS_DEFAULT_REGION: "us-east-1"
  TF_VERSION: "1.0.0"

before_script:
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - eval $(ssh-agent -s)
  - echo "$PRIVATE_KEY" | tr -d '\r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - ssh-keyscan -H 'endereco_sftp' >> ~/.ssh/known_hosts

test:
  stage: test
  image: golang:1.18
  script:
    - go test -v ./...

build:
  stage: build
  image: golang:1.18
  script:
    - go build -o myapp
    - zip -r sftp-lambda.zip myapp
  artifacts:
    paths:
      - sftp-lambda.zip
  only:
    - master

deploy:
  stage: deploy
  image: hashicorp/terraform:$TF_VERSION
  script:
    - terraform init
    - terraform apply -auto-approve
  only:
    - master
  environment:
    name: production

Passo 4: Integrando com o Databricks

Após o upload dos arquivos para o S3, a função Lambda deve acionar um job no Databricks. Isso pode ser feito utilizando a API do Databricks para iniciar jobs existentes.

package main

import (
 "bytes"
 "encoding/json"
 "fmt"
 "net/http"
)

// Estrutura para a requisição de iniciar um job no Databricks
type DatabricksJobRequest struct {
 JobID int `json:"job_id"`
}

// Função para acionar um job no Databricks
func triggerDatabricksJob(databricksInstance string, token string, jobID int) error {
 url := fmt.Sprintf("https://%s/api/2.0/jobs/run-now", databricksInstance)
 requestBody, _ := json.Marshal(DatabricksJobRequest{JobID: jobID})
 req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
 if err != nil {
  return err
 }

 req.Header.Set("Content-Type", "application/json")
 req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))

 client := &http.Client{}
 resp, err := client.Do(req)
 if err != nil {
  return err
 }
 defer resp.Body.Close()

 if resp.StatusCode != http.StatusOK {
  return fmt.Errorf("Failed to trigger Databricks job, status code: %d", resp.StatusCode)
 }

 return nil
}

func main() {
 // ... (código existente para conectar ao SFTP e carregar no S3)

 // Substitua pelos seus valores reais
 databricksInstance := "your-databricks-instance"
 databricksToken := "your-databricks-token"
 databricksJobID := 123 // ID do job que você deseja acionar

 // Acionar o job no Databricks após o upload para o S3
 err := triggerDatabricksJob(databricksInstance, databricksToken, databricksJobID)
 if err != nil {
  log.Fatal("Erro ao acionar o job do Databricks:", err)
 }

 fmt.Println("Job do Databricks acionado com sucesso")
}

Passo 5: Executando o Pipeline

Faça o push do código para o repositório GitLab para que o pipeline seja executado. Verifique se todos os passos são concluídos com sucesso e se a função Lambda está operacional e interagindo corretamente com o S3 e o Databricks.

Uma vez que você tenha o código completo e o arquivo .gitlab-ci.yml configurado, você pode executar o pipeline seguindo estes passos:

  • Faça o push do seu código para o repositório GitLab:
  git add .
  git commit -m "Adiciona função Lambda para integração SFTP, S3 e Databricks"
  git push origin master
git add .
git commit -m "Adiciona função Lambda para integração SFTP, S3 e Databricks"
git push origin master
´´´

  • O GitLab CI/CD detectará o novo commit e iniciará o pipeline automaticamente.
  • Acompanhe a execução do pipeline no GitLab acessando a seção CI/CD do seu repositório.
  • Se todos os estágios forem bem-sucedidos, sua função Lambda será implantada e pronta para ser usada.

Lembre-se de que você precisará configurar as variáveis de ambiente no GitLab CI/CD para armazenar informações sensíveis, como tokens de acesso e chaves privadas. Isso pode ser feito na seção ‘Settings’ > ‘CI / CD’ > ‘Variables’ do seu projeto GitLab.

Além disso, certifique-se de que o token do Databricks tenha as permissões necessárias para acionar jobs e que o job exista com o ID fornecido.

Conclusão

A automação de tarefas de engenharia de dados pode ser significativamente simplificada com o uso de ferramentas como GitLab CI/CD, Terraform e AWS Lambda. Ao seguir os passos descritos neste artigo, você pode criar um sistema robusto que automatiza a coleta e integração de dados entre SFTP, S3 e Databricks, tudo isso com a eficiência e a simplicidade da linguagem Go. Com essa abordagem, você estará bem equipado para lidar com os desafios de integração de dados em escala.

Meus contatos:

LinkedIn - Airton Lira Junior

iMasters - Airton Lira Junior

aws #lambda #terraform #gitlab #ci_cd #go #databricks #dataengineering #automation


版本声明 本文转载于:https://dev.to/airton_lirajunior_2ddebd/implementando-uma-lambda-com-gitlab-cicd-e-terraform-para-integracao-sftp-s3-e-databricks-em-go-5hc0?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 释放性能:Java Web 框架中的虚拟线程
    释放性能:Java Web 框架中的虚拟线程
    Level up your Java web applications with Virtual Threads — where speed meets simplicity, and performance breaks all records on the field! As Java cont...
    编程 发布于2024-11-08
  • 避免 React 中不必要的重新渲染
    避免 React 中不必要的重新渲染
    构建高性能 React 应用程序的关键之一是避免不必要的重新渲染。 React 的渲染引擎非常高效,但防止在不需要的地方重新渲染仍然至关重要。在这篇文章中,我们将介绍常见错误以及如何避免这些错误。 1. 使用 React.memo 记忆组件 当组件的 props 没有改变时,Memo...
    编程 发布于2024-11-08
  • 如何解决数据库连接中的“调用成员函数prepare() on null”错误?
    如何解决数据库连接中的“调用成员函数prepare() on null”错误?
    空成员函数错误:数据库连接中的问题遇到“Call to a member function prepare() on null”错误时,问题通常源于类实例中未初始化的变量。在您的情况下,问题在于缺少 $pdo 变量的初始化。在您的 Category 类中, fetch_all() 和 fetch_d...
    编程 发布于2024-11-08
  • Python 中 exit() 和 sys.exit() 有什么区别?
    Python 中 exit() 和 sys.exit() 有什么区别?
    Python 中的 Exit 和 sys.exit:差异和用法Python 提供了两个具有相似用途但具有不同功能的函数: exit( ) 和 sys.exit()。了解这两个函数之间的差异对于在各种情况下正确使用它们至关重要。exit()exit() 主要用于交互式 Python壳。它提供了一种终止...
    编程 发布于2024-11-08
  • 在 Slack、Python 自动化中为最后一刻的会议预订房间
    在 Slack、Python 自动化中为最后一刻的会议预订房间
    在繁忙的组织中,管理会议室的可用性可能是一项挑战,尤其是在最后一刻的临时预订方面。为了解决这个问题,我开发了一个基于 Python 的自动化工具,该工具将 Slack 与 Google Calendar 无缝集成,使员工能够快速检查房间可用性并预订房间以立即召开会议。 Python代码较短且易于修改...
    编程 发布于2024-11-08
  • 如何使用 pygame.draw.rect 在 Pygame 中绘制矩形?
    如何使用 pygame.draw.rect 在 Pygame 中绘制矩形?
    用Pygame绘制矩形在Python的Pygame库中,创建矩形是开发游戏的一项基本任务。 对于像 3.2 这样的 Pygame 版本,绘制矩形涉及使用 pygame.draw.rect 函数。实现此目的的方法如下:导入 Pygame 和基本常量:import pygame, sys from py...
    编程 发布于2024-11-08
  • 如何将 CSS 样式专门应用于 Internet Explorer 7、8 和 9?
    如何将 CSS 样式专门应用于 Internet Explorer 7、8 和 9?
    仅将 CSS 应用到 Internet Explorer将 CSS 的应用限制到特定版本的 Internet Explorer,例如 7、8 和9、利用 Microsoft 特定的媒体查询提供了一种有效的解决方案。在提供的示例中,CSS 代码旨在仅将 100% 的宽度应用于 IE 浏览器。以下是其工...
    编程 发布于2024-11-08
  • 为什么我的 jqGrid 编辑表单中的状态选择框选项值不正确?
    为什么我的 jqGrid 编辑表单中的状态选择框选项值不正确?
    jqgrid 在编辑框中选择下拉选项值不正确尽管在编辑表单中正确选择了“国家/地区”和“州”值,但“州”选择框中显示的选项值编辑表格时不正确。即使选择美国国家/地区后切换回英国国家/地区,此问题仍然存在。如何解决“州”选择框中不正确的选项值要解决此问题,需要正确加载编辑表单时,根据所选国家/地区值填...
    编程 发布于2024-11-08
  • 考虑到特定于平台的结尾,如何有效地从 Java 中的文件中删除换行符?
    考虑到特定于平台的结尾,如何有效地从 Java 中的文件中删除换行符?
    从 Java 中的文件中删除换行符在 Java 中,从文件中删除换行符可以通过替换所有出现的换行符来实现。但是,考虑特定于平台的行结尾以确保 Windows 和 Linux 之间的兼容性至关重要。要有效替换换行符,应使用以下步骤:将文件作为字符串读取: 使用 readFileAsString 等函数...
    编程 发布于2024-11-08
  • 如何从内容中删除 HTML 特殊字符?
    如何从内容中删除 HTML 特殊字符?
    删除 HTML 特殊字符在尝试生成 RSS 源文件时,您使用了 strip_tags 函数来从应用程序中删除 HTML 标记。但是,您遇到了一个缺点:strip_tags 无法删除 HTML 特殊代码字符,例如“ ”、“&”和“©”。要解决此问题,请考虑使用替代函数,例如...
    编程 发布于2024-11-08
  • 如何在Python中通过拆分和删除字符来解析和清理列表元素?
    如何在Python中通过拆分和删除字符来解析和清理列表元素?
    如何拆分列表元素并删除不需要的字符要拆分列表元素并删除不需要的字符,您可以使用split() 和列表理解技术的组合。以下是如何获得所需结果:在Python中,split()方法根据指定的分隔符将字符串划分为列表。默认情况下,它按空格字符进行分割,但您也可以传递可选的分隔符。要删除 \t 字符及其后面...
    编程 发布于2024-11-08
  • Wagtail 以编程方式创建页面翻译
    Wagtail 以编程方式创建页面翻译
    我找不到任何编程接口来创建页面翻译。所有逻辑似乎都在 wagtail.contrib.simple_translation.views. 的 SubmitTranslationView 中实现 因此,以编程方式访问这些内容的唯一方法是模拟访问视图的请求。我将其包装在一个名为translate_pag...
    编程 发布于2024-11-08
  • Java 切换初学者指南
    Java 切换初学者指南
    Java Switching 在 Java 中引入了 Switch 语句的概念,为复杂的 if-else 链提供了替代方案。 Switch 语句允许您将一个变量与多个可能的值进行比较,从而使您的代码更加高效和可读。 本指南涵盖了语法、不同数据类型的用法以及在 Java 中实现 switch 语句...
    编程 发布于2024-11-08
  • 如何更正 getMonth() 函数以在 JavaScript 中返回正确的月份?
    如何更正 getMonth() 函数以在 JavaScript 中返回正确的月份?
    JavaScript 中的 getMonth() 函数返回上个月在 JavaScript 中,getMonth() 方法返回指定日期的月份,从从 0(一月)开始。但是,当与格式为“Sun Jul 7 00:00:00 EDT 2013”​​的日期一起使用时,它可以提供上个月而不是预期的月份。这是因为...
    编程 发布于2024-11-08
  • 用 javascript 创建一个打字游戏来测量 wpm 速度
    用 javascript 创建一个打字游戏来测量 wpm 速度
    用 JavaScript 创建一个快速打字游戏 在本教程中,我们将创建一个简单的打字游戏,以 wpm 为单位测量我们的打字速度 - 每分钟单词数、每分钟字符数、拼写错误,并允许改进它。我们将只使用 javascript 和 jQuery(这并不是真正需要的,但它会让我们的打字游戏变...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3