Cómo desplegar una función de Azure Functions con FastAPI y GitHub

Daniel J. Saldaña - Aug 2 - - Dev Community

En este post, te explicaré cómo crear y desplegar una función de Azure Functions manualmente utilizando FastAPI y cómo integrar el proceso de creación con un repositorio de código de GitHub.

Paso 1: Configuración inicial de Azure Functions

  1. Crea una cuenta de Azure : Si no tienes una cuenta de Azure, puedes crear una en azure.com.

  2. Instala las herramientas de Azure :

Paso 2: Crear una función de Azure Functions desde el portal de Azure

  1. Inicia sesión en el Portal de Azure.

  2. Crea un nuevo recurso de Azure Functions :

  3. Configura la aplicación de funciones :

  4. Configuración del hosting :

  5. Configuración de supervisión :

  6. Configuración de implementación continua :

Paso 3: Configurar la implementación continua desde GitHub

  1. Configuración de GitHub :

  2. Configuración del flujo de trabajo :

  3. Configuración de autenticación :

Paso 4: Integrar FastAPI con Azure Functions

  1. Código de FastAPI : Asegúrate de que tu archivo main.py contenga el siguiente código:
import azure.functions as func

from typing import Any, List, Union, Optional

from fastapi import FastAPI, Body
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field

app = FastAPI()
app.title = "API de Daniel J. Saldaña"
app.version = "0.0.1"

class ExampleUpdateRequest(BaseModel):
    date: int

class Education(BaseModel):
    name: str
    description: Union[str, None] = None
    score: float = Field(description="Calificación obtenida", ge=0, le=10)

education = {
    "1": {"name": "Experto Universitario en Cloud Computing. Arquitecturas y Soluciones (AWS y Azure)", "description": "La Unir", "score": 9.0},
    "2": {"name": "Experto Universitario en Devops & Cloud", "description": "La Unir", "score": 9.0},
}

class Experience(BaseModel):
    name: str
    description: Union[str, None] = None
    time: Union[str, None] = None

experience = {
    "5": {"name": "Software Arquitect", "description": "Toma decisiones de diseño de alto nivel y dicta estándares técnicos 📋, incluyendo estándares de codificación de software, herramientas y plataformas. Dirijo el diseño y desarrollo de la arquitectura tecnológica de un sistema 🏗️, aplicación o plataforma. Para ello, me encargo de seleccionar el software adecuado para cada función, vigilar la implementación y coordinar la resolución de los problemas técnicos que puedan surgir, planificando técnicamente cada paso a seguir en la construcción de esa arquitectura 💬.", "time": "📆 2022 - Actualidad"},
    "4": {"name": "Site Reliability Engineering", "description": "Automatización de tareas operativas, creación de pipeline 🚀, diseño level design para garantizar la disponibilidad de las aplicaciones 🏗️, explotación de métricas e identificar, diagnosticar y resolver los problemas de aplicaciones 🧪.", "time": "📆 2022 - 2022"},
    "3": {"name": "DevOps Engineer", "description": "Desarrollo automatizaciones en la solución CI/CD interna 🔧. Cooperación con los equipos de Arquitectura en la fase de design thinking así como en las distintas fases de desarrollo de evolutivo 🗒️. Miembro del equipo de estrategia del Dominio de Ingeniera para definir nuevos procedimientos y modelos de trabajo ✍️.", "time": "📆 2020 - 2022"},
    "2": {"name": "SysAdmin Linux", "description": "Resolución de incidencias 🔴, automatización de procedimientos, creación y configuración de máquinas virtuales 🖥️, gestión de todo la infraestructura interna de la organización 🧮.", "time": "📆 2020 - 2020"},
    "1": {"name": "SysAdmin Linux/Windows", "description": "Intervenciones en máquinas físicas y virtuales y entornos de servidores compartidos ☁️, gestión en clusters de correo ✉️, implementación de reglas de seguridad 🔐.", "time": "📆 2016 - 2019"},
}

class Certifications(BaseModel):
    id: Optional[int] = None
    name: str
    description: Union[str, None] = None
    provider: Union[str, None] = None
    validity: Union[str, None] = None

certifications = {
    "1": {"name": "Microsoft Certified: Azure Network Engineer Associate", "description": "Earning Azure Network Engineer Associate validates skills and subject matter expertise in planning, implementing, and maintaining Azure networking solutions, including hybrid networking, connectivity, routing, security, and private access to Azure services. Professionals in this role deploy networking solutions using Azure Portal and other methods, including PowerShell, Azure Command-Line Interface (CLI), and Azure Resource Manager templates (ARM templates).", "provider": "Microsoft", "validity": "📆 2023 - 2024"},
    "2": {"name": "AWS Cloud Quest: Cloud Practitioner", "description": "Earners of this badge have demonstrated basic solution building knowledge using AWS services and have a fundamental understanding of AWS Cloud concepts. Badge earners have acquired hands-on experience with compute, networking, database and security services.", "provider": "AWS", "validity": "📆 Does not expire"},
}

@app.get("/hello-world/{date}", tags=["Example"], response_model=dict)
async def get_hello_world(date: int) -> dict:
    return {"message": f"Soy Goliat y tengo {date} años."}

@app.put("/hello-world/{date}", tags=["Example"], response_model=dict)
async def update_hello_world(date: int, request: ExampleUpdateRequest) -> dict:
    return {"message": f"Hola {request.date}, bienvenido a mi API."}

@app.post("/hello-world", tags=["Example"], response_model=dict)
async def create_hello_world(name: str = "Goliat") -> dict:
    return {"message": f"¡Hola {name}!"}

@app.get("/", tags=["Home"], response_model=dict)
def get_index() -> dict:
    return JSONResponse(content="Bienvenidos a la API de Daniel J. Saldaña")

@app.get("/aboutme", tags=["About me"], response_model=dict)
def get_aboutme() -> dict:
    return JSONResponse(content="Soy Software Arquitect🔥, con un background de DevOp,SRE,SysAdmin y especializado en provedores Cloud como AWS, Azure y GCP. Dispongo de un fuerte dominio de Arquitectura Cloud y Diseño de modelos de CI/CD. Vivo en Almería, España 🌍 tengo 30 años")

@app.get("/education", tags=["Education"], response_model=List[Education])
async def get_education() -> List[Education]:
    return JSONResponse(content=education)

@app.get("/education/{id}", tags=["Education"], response_model=Education)
async def get_education_by_id(id: str) -> Education:
    return JSONResponse(content=education[id])

@app.get("/experience", tags=["Experience"],response_model=List[Experience])
async def get_experience() -> List[Experience]:
    return JSONResponse(content=experience)

@app.get("/experience/{id}", tags=["Experience"], response_model=Certifications)
async def get_experience_by_id(id: str) -> Certifications:
    return JSONResponse(content=experience[id])

@app.get("/certifications", tags=["Certifications"], response_model=List[Certifications])
async def get_certifications() -> List[Certifications]:
    return JSONResponse(content=certifications)

@app.get("/certifications/{id}", tags=["Certifications"], response_model=Certifications)
async def get_education_by_id(id: str) -> Certifications:
    return JSONResponse(content=certifications[id])

@app.get("/certifications/", tags=["Certifications"], response_model=List[Certifications])
async def get_certifications_provider(provider: str) -> List[Certifications]:
    result = []
    for certification in certifications.values():
        if certification["provider"] == provider:
            result.append(certification)
    return JSONResponse(content=result)

Enter fullscreen mode Exit fullscreen mode
  1. Archivo function_app.py : Crea un archivo function_app.py con el siguiente contenido:

  2. Estructura de archivos : Asegúrate de que tu proyecto tenga la siguiente estructura de archivos:

  3. Archivo host.json : Asegúrate de que tu archivo host.json tenga la siguiente configuración:

  4. Archivo requirements.txt : Asegúrate de que tu archivo requirements.txt incluya las dependencias necesarias:

Paso 5: Desplegar la función

Formulario interactivo

  1. Empuja el código a GitHub : Asegúrate de que todo tu código esté empujado a la rama seleccionada en GitHub.

  2. Verifica la implementación : GitHub Actions se encargará de desplegar automáticamente tu aplicación de funciones en Azure cada vez que realices cambios en el repositorio. Puedes monitorear el progreso desde la pestaña de Actions en tu repositorio de GitHub.

  3. Probar la función :

¡Y eso es todo! Ahora tienes una función de Azure Functions desplegada con FastAPI y GitHub Actions.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player