diff --git a/sreagent-templates/bin/clone-agent.sh b/sreagent-templates/bin/clone-agent.sh index b863b265b..682c6dbcb 100755 --- a/sreagent-templates/bin/clone-agent.sh +++ b/sreagent-templates/bin/clone-agent.sh @@ -298,8 +298,15 @@ for i in $(seq 0 $((CONNECTOR_COUNT - 1))); do else _ok "Connector '${cname}' (${ctype}): ${dsrc}" fi + elif [[ -z "$dsrc" ]]; then + # ARM does not return dataSource on read -- neither does the data plane -- so an + # exported connector of a type that requires one always arrives empty. Deploying it + # fails from inside the ARM operation, one connector at a time, long after validation + # passed. Naming it here lets the operator supply it with --override first. + _warn "Connector '${cname}' (${ctype}): no dataSource; supply one before deploying, e.g." + _warn " --override connectors.${i}.properties.dataSource=" else - _ok "Connector '${cname}' (${ctype})" + _ok "Connector '${cname}' (${ctype}): ${dsrc}" fi done @@ -544,6 +551,7 @@ if [[ -n "$EXTRAS" ]]; then _warn "${MCP_COUNT} MCP connector(s) need data-plane overlay (ARM strips bearer tokens)" fi + # Knowledge & memories KNOWLEDGE_COUNT=$(jq '(.knowledge // []) | length' "$EXTRAS") KI_COUNT=$(jq '(.knowledgeItems // []) | length' "$EXTRAS") diff --git a/sreagent-templates/bin/export-agent.sh b/sreagent-templates/bin/export-agent.sh index 39a1f78ef..94e8fa3a4 100755 --- a/sreagent-templates/bin/export-agent.sh +++ b/sreagent-templates/bin/export-agent.sh @@ -1041,18 +1041,31 @@ for i in $(seq 0 $((CONNECTOR_COUNT - 1))); do ctype=$(echo "$CONNECTORS" | jq -r --argjson i "$i" '.[$i].properties.dataConnectorType') case "$ctype" in AppInsights) - # Only capture the FIRST AppInsights connector for the toggle + # Only capture the FIRST AppInsights connector for the toggle. + # ARM does not return dataSource on read, so this can come back empty. Enabling the + # connector without one makes the deployment fail with "DataSource is required", so + # the toggle is only set when a resource id was actually resolved. if [[ "$ENABLE_AI" == "false" ]]; then - ENABLE_AI=true - AI_RESOURCE_ID=$(echo "$CONNECTORS" | jq -r --argjson i "$i" '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""') - AI_APP_ID=$(echo "$CONNECTORS" | jq -r --argjson i "$i" '.[$i].properties.extendedProperties.appId // ""') + _ai_id=$(echo "$CONNECTORS" | jq -r --argjson i "$i" '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""') + if [[ -n "$_ai_id" ]]; then + ENABLE_AI=true + AI_RESOURCE_ID="$_ai_id" + AI_APP_ID=$(echo "$CONNECTORS" | jq -r --argjson i "$i" '.[$i].properties.extendedProperties.appId // ""') + else + _warn "AppInsights connector has no resolvable resource id — not enabling it on the clone" + fi fi ;; LogAnalytics) - # Only capture the FIRST LogAnalytics connector for the toggle + # Only capture the FIRST LogAnalytics connector for the toggle. See the note above. if [[ "$ENABLE_LAW" == "false" ]]; then - ENABLE_LAW=true - LAW_RESOURCE_ID=$(echo "$CONNECTORS" | jq -r --argjson i "$i" '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""') + _law_id=$(echo "$CONNECTORS" | jq -r --argjson i "$i" '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""') + if [[ -n "$_law_id" ]]; then + ENABLE_LAW=true + LAW_RESOURCE_ID="$_law_id" + else + _warn "LogAnalytics connector has no resolvable workspace id — not enabling it on the clone" + fi fi ;; AzureMonitor) diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index 1aa2eb35d..cb5a4e94a 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -1206,13 +1206,27 @@ for ($i = 0; $i -lt $CONNECTOR_COUNT; $i++) { $ctype = $CONNECTORS | jq -r --argjson i $i '.[$i].properties.dataConnectorType' switch ($ctype) { 'AppInsights' { - $ENABLE_AI = $true - $AI_RESOURCE_ID = $CONNECTORS | Invoke-Jq -Raw -Filter '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""' -ExtraArgs @('--argjson', 'i', "$i") - $AI_APP_ID = $CONNECTORS | Invoke-Jq -Raw -Filter '.[$i].properties.extendedProperties.appId // ""' -ExtraArgs @('--argjson', 'i', "$i") + # ARM does not return dataSource on read, so this can come back empty. Enabling + # the connector without one makes the deployment fail with "DataSource is + # required", so the toggle is only set when a resource id was actually resolved. + $aiId = $CONNECTORS | Invoke-Jq -Raw -Filter '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""' -ExtraArgs @('--argjson', 'i', "$i") + if (-not [string]::IsNullOrWhiteSpace($aiId)) { + $ENABLE_AI = $true + $AI_RESOURCE_ID = $aiId + $AI_APP_ID = $CONNECTORS | Invoke-Jq -Raw -Filter '.[$i].properties.extendedProperties.appId // ""' -ExtraArgs @('--argjson', 'i', "$i") + } else { + _warn 'AppInsights connector has no resolvable resource id - not enabling it on the clone' + } } 'LogAnalytics' { - $ENABLE_LAW = $true - $LAW_RESOURCE_ID = $CONNECTORS | Invoke-Jq -Raw -Filter '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""' -ExtraArgs @('--argjson', 'i', "$i") + # See the note above. + $lawId = $CONNECTORS | Invoke-Jq -Raw -Filter '.[$i].properties.dataSource // .[$i].properties.extendedProperties.armResourceId // ""' -ExtraArgs @('--argjson', 'i', "$i") + if (-not [string]::IsNullOrWhiteSpace($lawId)) { + $ENABLE_LAW = $true + $LAW_RESOURCE_ID = $lawId + } else { + _warn 'LogAnalytics connector has no resolvable workspace id - not enabling it on the clone' + } } 'AzureMonitor' { $ENABLE_AZMON = $true