Azure / iotedge

The IoT Edge OSS project
MIT License
1.45k stars 458 forks source link

Preserving desired properties when updating module in layered deployment #2914

Closed mahdighorbanpour closed 4 years ago

mahdighorbanpour commented 4 years ago

I was using azure IoT edge deployments and in the Azure pipeline, I delete the old deployment and re-create a new deployment with updated module versions. it was working perfectly fine, until I moved to layered deployment. now the deployment is working but desired properties of the modules will be deleted even though there is no "properties.desired" section as it is already mentioned in 1670

Expected Behavior

After a new deployment with the same id and module is created, we should keep the module's desired properties.

Current Behavior

Module desired properties will be deleted.

Steps to Reproduce

Provide a detailed set of steps to reproduce the bug.

  1. Create a layered deployment with one custom module
  2. After deployment on the device, on the Azure portal set the module desired properties inside the module twin
  3. Delete the deployment created in step 1, recreate the same deployment
  4. Check module twin after device received new changes

Device Information

Runtime Versions

Here is my deployment json file:

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired.modules.xxx": {
        "settings": {
          "image": "xxx",
          "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"x/tcp\":[{\"HostPort\":\"x\"}],\"x/tcp\":[{\"HostPort\":\"x\"}],\"x/tcp\":[{\"HostPort\":\"x\"}]}}}"
        },
        "type": "docker",
        "status": "running",
        "restartPolicy": "always",
        "version": "1.0",
        "env": {
          "ASPNETCORE_ENVIRONMENT": {
            "value": "Development"
          }
        }
      }
    },
    "$edgeHub": {
      "properties.desired": {
        "schemaVersion": "1.0",
        "routes": {
          "yyy": "FROM /messages/* INTO BrokeredEndpoint(\"/modules/yyy/inputs/deviceDataSink\")"
        },
        "storeAndForwardConfiguration": {
          "timeToLiveSecs": 7200
        }
      }
    }
  }
}
mahdighorbanpour commented 4 years ago

I tried to add my desired properties for the meoment inside deployment manifest.

This was my first deployment manifest ```json { "modulesContent": { "$edgeAgent": { "properties.desired.modules.xxx": { "settings": { "image": "xxxcontainerregistry.azurecr.io/xxx:20200505.1-0.0.17-alpha.1007", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"1433/tcp\":[{\"HostPort\":\"1433\"}],\"8000/tcp\":[{\"HostPort\":\"80\"}],\"8001/tcp\":[{\"HostPort\":\"8443\"}]}}}" }, "type": "docker", "status": "running", "restartPolicy": "always", "version": "1.0", "env": { "ASPNETCORE_ENVIRONMENT": { "value": "Development" } } } }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.0", "routes": { "yyy": "FROM /messages/* INTO BrokeredEndpoint(\"/modules/yyy/inputs/deviceDataSink\")" }, "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } } } } ```

After device recieved the deployment, I set "Module Identity Twin" manually from azure portal:

"properties": {
    "desired": {
        "P34WebMvc": {
                "ConnectionStrings": {
                    "Default": "Data Source=tcp:mssql-server-linux,1433;Initial Catalog=xxxDb;User Id=SA;Password=somepassword"
                },
                "someElse": "http://vvvvv"
            },
    }
}

then I added desired properties to deployment manifest like the way described in this link " If this layered deployment targeted a device where the same module was already applied, it would overwrite any existing desired properties. In order to update, instead of overwrite, desired properties, you can define a new subsection."

deployment manifest ```json { "modulesContent": { "$edgeAgent": { "properties.desired.modules.xxx": { "settings": { "image": "xxxcontainerregistry.azurecr.io/xxx:20200505.1-0.0.17-alpha.1007", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"1433/tcp\":[{\"HostPort\":\"1433\"}],\"8000/tcp\":[{\"HostPort\":\"80\"}],\"8001/tcp\":[{\"HostPort\":\"8443\"}]}}}" }, "type": "docker", "status": "running", "restartPolicy": "always", "version": "1.0", "env": { "ASPNETCORE_ENVIRONMENT": { "value": "Development" } } } }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.0", "routes": { "yyy": "FROM /messages/* INTO BrokeredEndpoint(\"/modules/yyy/inputs/deviceDataSink\")" }, "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } }, "xxx": { "properties.desired.layeredProperties": { "fake":"IgnoreMe" } } } } ```

The result was edgeAgent removed the modlue "xxx" first, after several minutes created the module again. At this moment I checked on Azure portal, "properties.desired.layeredProperties" is there but my manually added property ("P34WebMvc") has been removed again.

edgeAgent logs ``` <6> 2020-05-05 06:58:04.904 +00:00 [INF] - Plan execution started for deployment 152 <6> 2020-05-05 06:58:04.904 +00:00 [INF] - Executing command: "Stop module xxx" <6> 2020-05-05 06:58:05.610 +00:00 [INF] - Executing command: "Remove module xxx" <6> 2020-05-05 06:58:05.657 +00:00 [INF] - Executing command: "Saving xxx to store" <6> 2020-05-05 06:58:05.658 +00:00 [INF] - Plan execution ended for deployment 152 <6> 2020-05-05 06:58:05.796 +00:00 [INF] - Updated reported properties <6> 2020-05-05 06:58:10.941 +00:00 [INF] - Updated reported properties <6> 2020-05-05 07:00:31.435 +00:00 [INF] - Plan execution started for deployment 153 <6> 2020-05-05 07:00:31.435 +00:00 [INF] - Executing command: "Command Group: (\n [Create module xxx]\n [Start module xxx]\n)" <6> 2020-05-05 07:00:31.435 +00:00 [INF] - Executing command: "Create module xxx" <6> 2020-05-05 07:00:33.313 +00:00 [INF] - Executing command: "Start module xxx" <6> 2020-05-05 07:00:34.186 +00:00 [INF] - Plan execution ended for deployment 153 <6> 2020-05-05 07:00:34.352 +00:00 [INF] - Updated reported properties <6> 2020-05-05 07:00:39.498 +00:00 [INF] - Updated reported properties <6> 2020-05-05 07:06:31.615 +00:00 [INF] - Starting periodic operation refresh twin config... <6> 2020-05-05 07:06:31.637 +00:00 [INF] - Obtained Edge agent twin from IoTHub with desired properties version 153 and reported properties version 904. <6> 2020-05-05 07:06:31.638 +00:00 [INF] - Successfully completed periodic operation refresh twin config ```
damonbarry commented 4 years ago

@mahdighorbanpour I suspect you can't mix the two different means of updating a module's twin (manually and via automatic deployment)--one will override the other. But I'm double-checking...

mahdighorbanpour commented 4 years ago

@damonbarry I am using layered deployment. it's not an "Automatic deployment". Of course there is a base automatic deployment which should be applied first, but in that one I have not defined any desired properties. I didn't intend to add desired properties to my layered deployment, I added it only because without having "properties.desired" section insdie deployment manifest, my manually added properties will be removed, when a new deployment is applied.

damonbarry commented 4 years ago

@mahdighorbanpour I called it an automatic deployment because layered deployments are just an advanced scenario of automatic deployments. So I think the same rules apply to both--if you manually update desired properties they'll be overwritten by the automatic/layered deployment.

Still verifying this though....

damonbarry commented 4 years ago

@mahdighorbanpour I talked to someone in IoT Hub, and they think what you're trying to do should work. Can I get more details, specifically all the deployment layers including the base deployment, and the value of the module twin at each step? Also we can look at services logs in the backend if you let us know which IoT hub you tried this on...

mahdighorbanpour commented 4 years ago

Thank you. We're preparing this information for you and reproducing the problem on another IoTHub. Can we go offline for the exchange of other internals?

damonbarry commented 4 years ago

@mahdighorbanpour Sure, I sent you an email.

wjwater commented 4 years ago

@damonbarry So I understand that mixing manual and automatic deployment might not be possible. Could this be the reason of an issue I encounter? I update a module twin using the cli, but it get 'reverted' by the values of the automatic deployment. Do you know if a work-around is available? I assume it should be possible to update individual twins?

damonbarry commented 4 years ago

@wjwater Let's follow up on your issue in your original SO post. There's no indication of a bug in this repo at the moment, so SO is the better forum.

@mahdighorbanpour When you get a chance to send me the information we talked about, please reactivate this issue. Closing for now...

MaxThom commented 3 years ago

Hi, I have a similar issue, we have moved from base deployment to layered deployment. For the layered deployment, we use the Azure CLI in AzureDevops Pipeline. This is the pipeline task:

- task: AzureCLI@2
          displayName: Deploy to IoT Edge devices
          inputs:
            azureSubscription: ${{ parameters.azuresubscription }}
            scriptType: pscore
            scriptLocation: inlineScript
            inlineScript: |
              write-host '------> Starting deployment.'
              az config set extension.use_dynamic_install=yes_without_prompt
              write-host '------> Deleting previous deployment.'
              az iot edge deployment delete -d ${{ parameters.deploymentid }} -n ${{ parameters.iothubname }} --verbose
              write-host '------> Deploying new version.'
              start-sleep -seconds 10
              az iot edge deployment create -d ${{ parameters.deploymentid }} -n ${{ parameters.iothubname }} --priority ${{ parameters.priority }} --content ${{ parameters.deploymenttemplate }} --target-condition "${{ parameters.targetcondition }}" --layered
              write-host '------> Deployment complete!'

This is my layered deployment template:

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired.modules.SenseAI_TelemetrySwarm": {
        "settings": {
          "image": "${IMAGE_REPOSITORY}:${IMAGE_VERSION}-${IMAGE_PLATFORM}",
          "createOptions": ""
        },
        "type": "docker",
        "status": "running",
        "restartPolicy": "always",
        "version": "1.0"
      }
    },
    "$edgeHub": {
      "properties.desired.routes.AllTelemetryToAgentModule": {
        "priority": 0,
        "route": "FROM /messages/modules/SenseAI_TelemetrySwarm/outputs/* WHERE type = 'telemetry' INTO BrokeredEndpoint(\"/modules/SenseAI_TelemetryAgent/inputs/telemetryInput\")",
        "timeToLiveSecs": 7200
      }
    }
  }
}

I dont defined any desired properties for the layered deployment for my Swarm module, but each time its deployed. The module twin is reset. Is it because of deleting the deployment first? If I dont, I get an error in the deployment because of the name.

If im wrong on how to do it, what is the right solution ?

Thank you! Love the framework.

GO3LIN commented 2 years ago

It's a bit late but I think you should use properties.desired.layeredProperties instead of properties.desired on all the properties that you don't want to be overwritten.