Integración de IoT Central con Azure Pipelines para la integración continua y la entrega continua

Integración continua y entrega continua (CI/CD) hace referencia al proceso de desarrollo y entrega de software en ciclos cortos y frecuentes mediante canalizaciones de automatización. En este artículo se muestra cómo automatizar la compilación, la prueba y la implementación de una configuración de aplicación de IoT Central. Esta automatización permite a los equipos de desarrollo ofrecer versiones confiables con más frecuencia.

La integración continua comienza con una confirmación del código en una rama de un repositorio de código fuente. A continuación, cada confirmación se combina con las confirmaciones de otros desarrolladores para garantizar que no se han introducido conflictos. Los cambios se validan aún más creando una compilación y ejecutando pruebas automatizadas en esa compilación. En última instancia, este proceso da como resultado un artefacto o una agrupación de implementación para realizar la implementación en un entorno de destino. En este caso, el destino es una aplicación de Azure IoT Central.

Al igual que IoT Central forma parte de la solución de IoT más grande, IoT Central forma parte de la canalización de CI/CD. La canalización de CI/CD debe implementar toda la solución de IoT y todas las configuraciones en cada entorno, desde desarrollo hasta producción:

Diagrama que muestra las fases de una canalización típica de CI/CD.

IoT Central es una plataforma como servicio de aplicaciones que tiene requisitos de implementación diferentes de los componentes de plataforma como servicio . En IoT Central, se implementan configuraciones y plantillas de dispositivo. Estas configuraciones y plantillas de dispositivo se administran e integran en la canalización de versión mediante las API.

Aunque es posible automatizar la creación de aplicaciones de IoT Central, debe crear una aplicación en cada entorno antes de desarrollar la canalización de CI/CD.

Mediante la API REST de Azure IoT Central, puede integrar configuraciones de aplicaciones de IoT Central en la canalización de versión.

En esta guía se explica la creación de una canalización que actualiza una aplicación de IoT Central en función de los archivos de configuración administrados en GitHub. Esta guía tiene instrucciones específicas para la integración con Azure Pipelines, pero podría adaptarse para incluir IoT Central en cualquier canalización de versión compilada mediante herramientas como Tekton, Jenkins, GitLab o Acciones de GitHub.

En esta guía, creará una canalización que solo aplica una configuración de IoT Central a una sola instancia de una aplicación de IoT Central. Debe integrar los pasos en una canalización más grande que implemente toda la solución y la promueva desde desarrollo pasando por Control de calidad y preproducción hasta llegar a producción, realizando todas las pruebas necesarias a lo largo del proceso.

Actualmente, los scripts no transfieren la siguiente configuración entre instancias de IoT Central: paneles, vistas, configuración personalizada en plantillas de dispositivo, plan de precios, personalizaciones de experiencia de usuario, imagen de aplicación, reglas, trabajos programados, trabajos guardados y grupos de inscripción.

Actualmente, los scripts no quitan la configuración de la aplicación de IoT Central de destino que no existe en el archivo de configuración.

Requisitos previos

Necesita los siguientes requisitos previos para seguir los pasos de esta guía:

Descarga del código de ejemplo

Para empezar, bifurque el repositorio de GitHub de CI/CD de IoT Central y, después, clone la bifurcación en la máquina local:

  1. Para bifurcar el repositorio de GitHub, abra el repositorio de GitHub de CI/CD de IoT Central y seleccione Bifurcar.

  2. Clone la bifurcación del repositorio en la máquina local; para ello, abra una ventana de consola o Bash y ejecute el siguiente comando.

    git clone https://github.com/{your GitHub username}/iot-central-CICD-sample
    

Creación de una entidad de servicio

Aunque Azure Pipelines se puede integrar directamente con un almacén de claves, una canalización necesita una entidad de servicio para algunas interacciones dinámicas del almacén de claves, como capturar secretos para destinos de exportación de datos.

Para crear una entidad de servicio cuyo ámbito sea la suscripción, siga estos pasos:

  1. Ejecute el comando siguiente para crear una entidad de servicio:

    az ad sp create-for-rbac -n DevOpsAccess --scopes /subscriptions/{your Azure subscription Id} --role Contributor
    
  2. Anote los valores de password, appId y tenant, ya que los necesitará más adelante.

  3. Agregue la contraseña de la entidad de servicio como un secreto llamado SP-Password al almacén de claves de producción:

    az keyvault secret set --name SP-Password --vault-name {your production key vault name} --value {your service principal password}
    
  4. Conceda permiso a la entidad de servicio para leer secretos del almacén de claves:

    az keyvault set-policy --name {your production key vault name} --secret-permissions get list --spn {the appId of the service principal}
    

Generación de tokens de API de IoT Central

En esta guía, la canalización usa tokens de API para interactuar con las aplicaciones de IoT Central. También es posible usar una entidad de servicio.

Nota:

Los tokens de API de IoT Central expiran al cabo de un año.

Realice los pasos siguientes con las aplicaciones de IoT Central de desarrollo y producción.

  1. En la aplicación de IoT Central, seleccione Permisos y, después, Tokens de API.

  2. Seleccione Nuevo.

  3. Asigne un nombre al token, especifique la organización de nivel superior de la aplicación y establezca el rol en Administrador de aplicaciones.

  4. Anote el token de API de la aplicación de IoT Central de desarrollo. Lo usará más adelante al ejecutar el script IoTC-Config.ps1.

  5. Guarde el token generado por la aplicación de IoT Central de producción como un secreto llamado API-Token en el almacén de claves de producción:

    az keyvault secret set --name API-Token --vault-name {your production key vault name} --value '{your production app API token}'
    

Generación de un archivo de configuración

Estos pasos generan un archivo de configuración JSON para el entorno de desarrollo basado en una aplicación de IoT Central existente. También se descargan todas las plantillas de dispositivo existentes de la aplicación.

  1. Ejecute el siguiente script de PowerShell 7 en la copia local del repositorio de CI/CD de IoT Central:

    cd .\iot-central-CICD-sample\PowerShell\
    .\IoTC-Config.ps1
    
  2. Siga las instrucciones para iniciar sesión en la cuenta de Azure.

  3. Después de iniciar sesión, el script muestra el menú de opciones de configuración de IoTC. El script puede generar un archivo de configuración a partir de una aplicación de IoT Central existente y aplicar una configuración a otra aplicación de IoT Central.

  4. Seleccione la opción 1 para generar un archivo de configuración.

  5. Escriba los parámetros necesarios y presione Entrar:

    • Token de API que generó para la aplicación de IoT Central de desarrollo.
    • Subdominio de la aplicación de IoT Central de desarrollo.
    • Escriba ..\Config\Dev, que es la carpeta donde se almacenará el archivo de configuración y las plantillas de dispositivo.
    • Nombre del almacén de claves de desarrollo.
  6. El script crea una carpeta denominada IoTC Configuration en la carpeta Config\Dev de la copia local del repositorio. Esta carpeta contiene un archivo de configuración y una carpeta denominada Device Models de todas las plantillas de dispositivo de la aplicación.

Modifique el archivo de configuración

Ahora que tiene un archivo de configuración que representa la configuración de la instancia de aplicación de IoT Central de desarrollo, realice los cambios necesarios antes de aplicar esta configuración a la instancia de aplicación de IoT Central de producción.

  1. Cree una copia de la carpeta Dev creada anteriormente y llámela Production.

  2. Abra IoTC-Config.json en la carpeta Production mediante un editor de texto.

  3. El archivo tiene varias secciones. Sin embargo, si la aplicación no usa una configuración determinada, esa sección se omite del archivo:

    {
      "APITokens": {
        "value": [
          {
            "id": "dev-admin",
            "roles": [
              {
                "role": "ca310b8d-2f4a-44e0-a36e-957c202cd8d4"
              }
            ],
            "expiry": "2023-05-31T10:47:08.53Z"
          }
        ]
      },
      "data exports": {
        "value": [
          {
            "id": "5ad278d6-e22b-4749-803d-db1a8a2b8529",
            "displayName": "All telemetry to blob storage",
            "enabled": false,
            "source": "telemetry",
            "destinations": [
              {
                "id": "393adfc9-0ed8-45f4-aa29-25b5c96ecf63"
              }
            ],
            "status": "notStarted"
          }
        ]
      },
      "device groups": {
        "value": [
          {
            "id": "66f41d29-832d-4a12-9e9d-18932bee3141",
            "displayName": "MXCHIP Getting Started Guide - All devices"
          },
          {
            "id": "494dc749-0963-4ec1-89ff-e1de2228e750",
            "displayName": "RS40 Occupancy Sensor - All devices"
          },
          {
            "id": "dd87877d-9465-410b-947e-64167a7a1c39",
            "displayName": "Cascade 500 - All devices"
          },
          {
            "id": "91ceac5b-f98d-4df0-9ed6-5465854e7d9e",
            "displayName": "Simulated devices"
          }
        ]
      },
      "organizations": {
        "value": []
      },
      "roles": {
        "value": [
          {
            "id": "344138e9-8de4-4497-8c54-5237e96d6aaf",
            "displayName": "Builder"
          },
          {
            "id": "ca310b8d-2f4a-44e0-a36e-957c202cd8d4",
            "displayName": "Administrator"
          },
          {
            "id": "ae2c9854-393b-4f97-8c42-479d70ce626e",
            "displayName": "Operator"
          }
        ]
      },
      "destinations": {
        "value": [
          {
            "id": "393adfc9-0ed8-45f4-aa29-25b5c96ecf63",
            "displayName": "Blob destination",
            "type": "blobstorage@v1",
            "authorization": {
              "type": "connectionString",
              "connectionString": "DefaultEndpointsProtocol=https;AccountName=yourexportaccount;AccountKey=*****;EndpointSuffix=core.windows.net",
              "containerName": "dataexport"
            },
            "status": "waiting"
          }
        ]
      },
      "file uploads": {
        "connectionString": "FileUpload",
        "container": "fileupload",
        "sasTtl": "PT1H"
      },
      "jobs": {
        "value": []
      }
    }
    
  4. Si la aplicación usa cargas de archivos, el script crea un secreto en el almacén de claves de desarrollo con el valor que se muestra en la propiedad connectionString. Cree un secreto con el mismo nombre en el almacén de claves de producción que contenga la cadena de conexión de la cuenta de almacenamiento de producción. Por ejemplo:

    az keyvault secret set --name FileUpload --vault-name {your production key vault name} --value '{your production storage account connection string}'
    
  5. Si la aplicación usa exportaciones de datos, agregue secretos para los destinos al almacén de claves de producción. El archivo de configuración no contiene ningún secreto real para el destino; los secretos se almacenan en el almacén de claves.

  6. Actualice los secretos del archivo de configuración con el nombre del secreto del almacén de claves.

    Tipo de destino Propiedad que se va a cambiar
    Cola de Service Bus connectionString
    Tema de Service Bus connectionString
    Azure Data Explorer clientSecret
    Azure Blob Storage connectionString
    Event Hubs connectionString
    Webhook sin autenticación N/D

    Por ejemplo:

    "destinations": {
      "value": [
        {
          "id": "393adfc9-0ed8-45f4-aa29-25b5c96ecf63",
          "displayName": "Blob destination",
          "type": "blobstorage@v1",
          "authorization": {
            "type": "connectionString",
            "connectionString": "Storage-CS",
            "containerName": "dataexport"
          },
          "status": "waiting"
        }
      ]
    }
    
  7. Para cargar la carpeta Configuration en el repositorio de GitHub, ejecute los siguientes comandos desde la carpeta IoTC-CICD-howto.

     git add Config
     git commit -m "Adding config directories and files"
     git push
    

Crear una canalización

  1. Abra la organización de Azure DevOps en un explorador web; para ello, vaya a https://dev.azure.com/{your DevOps organization}.
  2. Seleccione Nuevo proyecto para crear un nuevo proyecto.
  3. Asigne un nombre al proyecto y una descripción opcional y, luego, seleccione Crear.
  4. En la página Bienvenido al proyecto, seleccione Canalizaciones y, luego, Crear canalización.
  5. Seleccione GitHub como ubicación del código.
  6. Seleccione Autorizar a Azure Pipelines para permitir que Azure Pipelines acceda a la cuenta de GitHub.
  7. En la página Seleccionar un repositorio, elija la bifurcación del repositorio de GitHub de CI/CD de IoT Central.
  8. Cuando se le pida que inicie sesión en GitHub y proporcione permiso para que Azure Pipelines acceda al repositorio, seleccione Aprobar e instalar.
  9. En la página Configurar la canalización, seleccione Canalización inicial para comenzar. Se muestra azure-pipelines.yml para que la modifique.

Creación de un grupo de variables

Una manera sencilla de integrar los secretos del almacén de claves en una canalización es mediante grupos de variables. Use un grupo de variables para asegurarse de que los secretos adecuados están disponibles para el script de implementación. Para crear un grupo de variables, siga estos pasos:

  1. Seleccione Biblioteca en la sección Canalizaciones del menú de la izquierda.

  2. Seleccione + Grupo de variables.

  3. Escriba keyvault como nombre del grupo de variables.

  4. Habilite el botón de alternancia para vincular los secretos de un almacén de claves de Azure.

  5. Seleccione su suscripción de Azure y autorícela. A continuación, seleccione el nombre del almacén de claves de producción.

  6. Seleccione Agregar para empezar a agregar variables al grupo.

  7. Agregue lo siguientes secretos:

    • Clave de API de IoT Central de la aplicación de producción. Llamó a este secreto API-Token cuando lo creó.
    • La contraseña de la entidad de servicio que creó anteriormente. Llamó a este secreto SP-Password cuando lo creó.
  8. Seleccione Aceptar.

  9. Seleccione Guardar para guardar el grupo de variables.

Configuración de la canalización

Ahora, configure la canalización para insertar los cambios de configuración en la aplicación de IoT Central:

  1. Seleccione Canalizaciones en la sección Canalizaciones del menú de la izquierda.

  2. Reemplace el contenido del archivo YAML de canalización por el siguiente archivo YAML. La configuración da por hecho que el almacén de claves de producción contiene lo siguiente:

    • El token de API de la aplicación de IoT Central de producción en un secreto denominado API-Token.
    • La contraseña de la entidad de servicio en un secreto denominado SP-Password.

    Reemplace los valores de -AppName y -KeyVault por los valores adecuados para las instancias de producción.

    Los valores de -AppId y -TenantId se anotaron cuando se creó la entidad de servicio.

    trigger:
    - master
    variables:
    - group: keyvault
    - name: buildConfiguration
      value: 'Release'
    steps:
    - task: PowerShell@2
      displayName: 'IoT Central'
      inputs:
        filePath: 'PowerShell/IoTC-Task.ps1'
        arguments: '-ApiToken "$(API-Token)" -ConfigPath "Config/Production/IoTC Configuration" -AppName "{your production IoT Central app name}" -ServicePrincipalPassword (ConvertTo-SecureString "$(SP-Password)" -AsPlainText -Force) -AppId "{your service principal app id}" -KeyVault "{your production key vault name}" -TenantId "{your tenant id}"'
        pwsh: true
        failOnStderr:  true
    
  3. Seleccione Guardar y ejecutar.

  4. El archivo YAML se guarda en el repositorio de GitHub, por lo que debe proporcionar un mensaje de confirmación y, luego, seleccionar de nuevo Guardar y ejecutar.

La canalización está en cola. Puede tardar unos minutos en ejecutarse.

La primera vez que ejecute la canalización, se le pedirá que le conceda permisos para que acceda a la suscripción y al almacén de claves. Seleccione Permitir y, de nuevo, Permitir para cada recurso.

Cuando el trabajo de canalización finalice correctamente, inicie sesión en la aplicación de IoT Central de producción y compruebe que la configuración se aplicó según lo previsto.

Promover los cambios de desarrollo a producción

Ahora que tiene una canalización que funciona, puede administrar las instancias de IoT Central directamente mediante los cambios de configuración. Puede cargar nuevas plantillas de dispositivo en la carpeta Device Models y realizar cambios directamente en el archivo de configuración. Este método le permite tratar la configuración de la aplicación de IoT Central igual que cualquier otro código.

Paso siguiente

Ahora que sabe cómo integrar configuraciones de IoT Central en las canalizaciones de CI/CD, se recomienda aprender a Administrar y supervisar aplicaciones de IoT Central.