diff --git a/samples/media-connector-invoke-test/.config_aio_connectors_namespace b/samples/media-connector-invoke-test/.config_aio_connectors_namespace new file mode 100644 index 0000000..381b8a4 --- /dev/null +++ b/samples/media-connector-invoke-test/.config_aio_connectors_namespace @@ -0,0 +1 @@ +azure-iot-operations \ No newline at end of file diff --git a/samples/media-connector-invoke-test/.config_aio_namespace b/samples/media-connector-invoke-test/.config_aio_namespace new file mode 100644 index 0000000..381b8a4 --- /dev/null +++ b/samples/media-connector-invoke-test/.config_aio_namespace @@ -0,0 +1 @@ +azure-iot-operations \ No newline at end of file diff --git a/samples/media-connector-invoke-test/.config_resources_path b/samples/media-connector-invoke-test/.config_resources_path new file mode 100644 index 0000000..8348376 --- /dev/null +++ b/samples/media-connector-invoke-test/.config_resources_path @@ -0,0 +1 @@ +${PSScriptRoot}/resources diff --git a/samples/media-connector-invoke-test/Install-ResourceFile.ps1 b/samples/media-connector-invoke-test/Install-ResourceFile.ps1 new file mode 100644 index 0000000..2e5d34d --- /dev/null +++ b/samples/media-connector-invoke-test/Install-ResourceFile.ps1 @@ -0,0 +1,34 @@ +#Requires -Version 7 +<# + Install a resource file. +#> +param ( + [Parameter( + Mandatory=$true, + HelpMessage="The resource file.")] + [string]$resourceFile +) + +Write-Host "`n" +Write-Host (Split-Path -Path $PSCommandPath -Leaf).ToUpper() -ForegroundColor White + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$resourcesDirectory = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_resources_path") -Raw).Trim() +$resourcesDirectory = $ExecutionContext.InvokeCommand.ExpandString(${resourcesDirectory}) +Write-Host "Resources directory: $resourcesDirectory" + +Write-Host "Resource file: $resourceFile" + +$fileFullPath=(Join-Path -Path $resourcesDirectory -ChildPath $resourceFile) +Write-Host "Resource file full path: ${fileFullPath}" + +Write-Host "Applying the resource..." +. kubectl apply -n ${aioConnectorsNamespace} -f ${fileFullPath} +If ($LastExitCode -ne 0) { + Write-Host "Error: The resource could not be applied." + Exit $LastExitCode +} Else { + Write-Host "The resource was applied successfully.`n" +} diff --git a/samples/media-connector-invoke-test/Invoke-ResourceInstallMonitorAndUninstall.ps1 b/samples/media-connector-invoke-test/Invoke-ResourceInstallMonitorAndUninstall.ps1 new file mode 100644 index 0000000..4c66e49 --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-ResourceInstallMonitorAndUninstall.ps1 @@ -0,0 +1,60 @@ +#Requires -Version 7 +<# + Install a resource pair (aep/asset), monitor it, and uninstall it. +#> +param ( + [Parameter( + Mandatory, + HelpMessage="The AEP name.")] + [string]$aepName = "", + [Parameter( + Mandatory, + HelpMessage="The asset name.")] + [string]$assetName = "", + [Parameter( + Mandatory, + HelpMessage="The datapoint name.")] + [string]$datapointName = "", + [Parameter( + Mandatory, + HelpMessage="The monitor expression.")] + [string]$monitorExpresion = "" +) + +Write-Host "`n" +Write-Host (Split-Path -Path $PSCommandPath -Leaf).ToUpper() -ForegroundColor White + +. (Join-Path $PSScriptRoot "Test-Prerequisites.ps1") | Out-Null + +$aioNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +Write-Host "AEP Name: $aepName" + +Write-Host "Asset Name: $assetName" + +Write-Host "Datapoint Name: $datapointName" + +Write-Host "Installing the resource files..." +. (Join-Path $PSScriptRoot "Install-ResourceFile.ps1") -resourceFile "${aepName}.yaml" +. (Join-Path $PSScriptRoot "Install-ResourceFile.ps1") -resourceFile "${assetName}.yaml" + +Write-Host "Waiting for the snapshot-to-mqtt task to be ready...`n" +Start-Sleep -Seconds 3 + +try { + Write-Host "Starting the monitor command...`n" + $monitorExpresion = $ExecutionContext.InvokeCommand.ExpandString(${monitorExpresion}) + Invoke-Expression "${monitorExpresion}" + +} finally { + + Write-Host "Uninstalling the resource files...`n" + . (Join-Path $PSScriptRoot "Uninstall-ResourceFile.ps1") -resourceFile "${assetName}.yaml" + . (Join-Path $PSScriptRoot "Uninstall-ResourceFile.ps1") -resourceFile "${aepName}.yaml" + + Write-Host "Snapshot-to-mqtt task test completed.`n" +} diff --git a/samples/media-connector-invoke-test/Invoke-TestClipToFsAutostart.ps1 b/samples/media-connector-invoke-test/Invoke-TestClipToFsAutostart.ps1 new file mode 100644 index 0000000..2a7fcc4 --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-TestClipToFsAutostart.ps1 @@ -0,0 +1,20 @@ +#Requires -Version 7 + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$aepName = "aep-public-http-anonymous-1" +Write-Host "AEP name: $aepName" + +$assetName = "asset-public-http-anonymous-1-clip-to-fs-autostart" +Write-Host "Asset name: $assetName" + +$datapointName = "clip-to-fs" +Write-Host "Datapoint name: $datapointName" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-ResourceInstallMonitorAndUninstall.ps1") ` + -aepName $aepName ` + -assetName $assetName ` + -datapointName $datapointName ` + -monitorExpresion ` + "& (Join-Path -Path $PSScriptRoot -ChildPath `"Start-FileSystemMonitor.ps1`") -pathToMonitor /tmp/$aioConnectorsNamespace/data/$assetName/" diff --git a/samples/media-connector-invoke-test/Invoke-TestSnapshotToFsAutostart.ps1 b/samples/media-connector-invoke-test/Invoke-TestSnapshotToFsAutostart.ps1 new file mode 100644 index 0000000..680749b --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-TestSnapshotToFsAutostart.ps1 @@ -0,0 +1,20 @@ +#Requires -Version 7 + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$aepName = "aep-public-http-anonymous-1" +Write-Host "AEP name: $aepName" + +$assetName = "asset-public-http-anonymous-1-snapshot-to-fs-autostart" +Write-Host "Asset name: $assetName" + +$datapointName = "snapshot-to-fs" +Write-Host "Datapoint name: $datapointName" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-ResourceInstallMonitorAndUninstall.ps1") ` + -aepName $aepName ` + -assetName $assetName ` + -datapointName $datapointName ` + -monitorExpresion ` + "& (Join-Path -Path $PSScriptRoot -ChildPath `"Start-FileSystemMonitor.ps1`") -pathToMonitor /tmp/$aioConnectorsNamespace/data/$assetName/" diff --git a/samples/media-connector-invoke-test/Invoke-TestSnapshotToMqttAutostart.ps1 b/samples/media-connector-invoke-test/Invoke-TestSnapshotToMqttAutostart.ps1 new file mode 100644 index 0000000..47c1fa0 --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-TestSnapshotToMqttAutostart.ps1 @@ -0,0 +1,20 @@ +#Requires -Version 7 + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$aepName = "aep-public-http-anonymous-1" +Write-Host "AEP name: $aepName" + +$assetName = "asset-public-http-anonymous-1-snapshot-to-mqtt-autostart" +Write-Host "Asset name: $assetName" + +$datapointName = "snapshot-to-mqtt" +Write-Host "Datapoint name: $datapointName" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-ResourceInstallMonitorAndUninstall.ps1") ` + -aepName $aepName ` + -assetName $assetName ` + -datapointName $datapointName ` + -monitorExpresion ` + "& (Join-Path -Path $PSScriptRoot -ChildPath `"Start-MqttListener.ps1`") -listenTopics $aioConnectorsNamespace/data/$assetName/#" diff --git a/samples/media-connector-invoke-test/Invoke-TestStreamToRtspAutostart.ps1 b/samples/media-connector-invoke-test/Invoke-TestStreamToRtspAutostart.ps1 new file mode 100644 index 0000000..37acd74 --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-TestStreamToRtspAutostart.ps1 @@ -0,0 +1,21 @@ +#Requires -Version 7 + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$aepName = "aep-public-http-anonymous-1" +Write-Host "AEP name: $aepName" + +$assetName = "asset-public-http-anonymous-1-stream-to-rtsp-autostart" +Write-Host "Asset name: $assetName" + +$datapointName = "stream-to-rtsp" +Write-Host "Datapoint name: $datapointName" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-ResourceInstallMonitorAndUninstall.ps1") ` + -aepName $aepName ` + -assetName $assetName ` + -datapointName $datapointName ` + -monitorExpresion ` + "& (Join-Path -Path $PSScriptRoot -ChildPath `"Start-RtspStreamViewer.ps1`") -assetName $assetName ; ` + try { Write-Host `"`nHit Ctrl+C to terminate`" ; Start-Sleep -Seconds 3600 } finally { Write-Host `"`nContinuing...`n`" }" diff --git a/samples/media-connector-invoke-test/Overview.md b/samples/media-connector-invoke-test/Overview.md new file mode 100644 index 0000000..7577bd7 --- /dev/null +++ b/samples/media-connector-invoke-test/Overview.md @@ -0,0 +1,29 @@ +# What is the media connector? + +The media connector makes media from media sources such as edge attached cameras available to other Azure IoT Operations components. The media connector is secure, performant, and can connect to the following media sources: + +| Media source | Example URLs | Notes | +|--------------| ---------------|-------| +| Edge attached camera | `file://host/dev/video0``file://host/dev/usb0` | No authentication required. The URL refers to the device file. Connects to a node using USB, FireWire, MIPI, or proprietary interface. | +| IP camera | `rtsp://192.168.178.45:554/stream1` | JPEG over HTTP for snapshots, RTSP/RTCP/RTP/MJPEG-TS for video streams. An IP camera might also expose a standard ONVIF control interface. | +| Media server | `rtsp://192.168.178.45:554/stream1` | JPEG over HTTP for snapshots, RTSP/RTCP/RTP/MJPEG-TS for video streams. A media server can also serve images and videos using URLs such as `ftp://host/path` or `smb://host/path` | +| Media file | `http://camera1/snapshot/profile1``nfs://server/path/file.extension`` file://localhost/media/path/file.mkv` | Any media file with a URL accessible from the cluster. | +| Media folder | `file://host/path/to/folder/``ftp://server/path/to/folder/` | A folder, accessible from the cluster, that contain media files such as snapshots or clips. | + +Example uses of the media connector include: + +- Capture snapshots from a video stream or from an image URL and publish them to an MQTT topic. A subscriber to the MQTT topic can use the captured images for further processing or analysis. + +- Save video streams to a local file system on your cluster. [Edge Storage Accelerator](https://learn.microsoft.com/azure/azure-arc/edge-storage-accelerator/) can provide a reliable and fault-tolerant solution for uploading the captured video to the cloud for storage or processing. + +- Proxy a live video stream from a camera to an endpoint that an operator can access. For security and performance reasons, only the media connector should have direct access to an edge camera. The media connector uses a separate media server component to stream video to an operator's endpoint. This media server can transcode to a variety of protocols such as RTSP, RTCP, SRT, and HLS. + +## How does it relate to Azure IoT Operations? + +The media connector component is part of Azure IoT Operations. The connector deploys to an Arc-enabled Kubernetes cluster on the edge as part of an Azure IoT Operations deployment. The connector interacts with other Azure IoT Operations elements, such as: + +- _Asset endpoints_, which are custom resources in your Kubernetes cluster that define connections to resources such as cameras. An asset endpoint configuration includes the URL of the media source, the type of media source, and any credentials that are needed to access the media source. The media connector uses an asset endpoint to access the media source. + +- _Assets_, which in Azure IoT Operations Preview are logical entities that you create to represent a real assets such as cameras. An Azure IoT Operations camera asset can have properties, tags, and video streams. + +- The Azure IoT Operations portal, which is a web UI that provides a unified experience for you to manage assets such as cameras. You can use the portal to configure the assets and asset endpoints that the media connector uses to access media sources. diff --git a/samples/media-connector-invoke-test/README.md b/samples/media-connector-invoke-test/README.md index 113becf..0e38f32 100644 --- a/samples/media-connector-invoke-test/README.md +++ b/samples/media-connector-invoke-test/README.md @@ -1,8 +1,102 @@ -# Azure IoT Operations (AIO) Media Connector Demo - -> [!NOTE] -> Ensure you're using Azure IoT Operations version 1.0.0a3 or later before moving forward. +# Azure IoT Operations media connector demo ## Introduction -This collection consists of .yaml files that could be utilized by the sample commands found in the introductory document. \ No newline at end of file +This document describes the Azure IoT Operations media connector demo package. + +The Azure IoT Operations media connector is part of the Azure IoT Operations platform: + +- It is designed to be secure, scalable and fault-tolerant. +- It is responsible for the ingestion, storage, and distribution of media content. +- It takes care of the management of media metadata and the generation of media thumbnails. + +## Demo environment diagram + +The demo environment consists of the following components: + +![Demo environment diagram](media-connector-demo.png) + +The dotted lines represent connections and components that are possible but not show in the demo package. + +## Getting started + +1. The scripts are designed to run on PowerShell 7 or newer. + - You can test if you have the necessary prerequisites by running `Test-Prerequisites.ps1`. + - The *Installation of prerequisites* section below has useful relevant information. + - This demo folder should be in a path without spaces. +1. [Deploy Azure IoT Operations](https://aka.ms/getAzure IoT Operations). + - The Azure IoT Operations Kubernetes cluster should be configured as the `kubectl` current context. +1. Upgrade the public preview components by running the script `Update-Azure IoT OperationsMediaConnector.ps1` in the `update-Azure IoT Operations/` folder. +1. Install the media server using the files in the `media-server/` folder. +1. You should have a listener without TLS configured on port 1883. + - You can verify by calling the `Update-Azure IoT OperationsMqEndpointFile.ps1` script. + - You can use the files under `broker-listener/` to deploy this. +1. Then you can run each of the test scripts `Invoke-Test*.ps1` to run different test scenarios: + - `Invoke-TestSnapshotToMqttAutostart.ps1` takes snapshots from the demo stream and publishes them to the MQTT broker. + - `Invoke-TestSnapshotToFsAutostart.ps1` takes snapshots from the demo stream and writes them as files to the file system. + - `Invoke-TestClipToFsAutostart.ps1` creates clips at regular intervals from the demo stream and writes them as files to the file system. + - `Invoke-TestStreamToRtspAutostart.ps1` pushes the demo stream to a media server, from where it can be retrieved. + + The scripts deploy the endpoint and asset and monitors their activity. Use `Ctrl+C` to end the monitoring, remove the endpoint and asset and terminate the script. + +## Installation of prerequisites + +To install the prerequisites you can follow the instructions below. + +These might not be the preferred installation procedure for your system and IT environment. + +Check with your administrator before installing tools. + +### Windows + +Run these commands from the command line: + +`winget install -e --id Microsoft.PowerShell` +`winget install -e --id Kubernetes.kubectl` +`winget install -e --id Microsoft.AzureCLI` +`winget install -e --id Helm.Helm` +`winget install -e --id EclipseFoundation.Mosquitto` + +You might need to add `C:\Program Files\mosquitto` and `helm.exe` to your PATH. + +### Ubuntu GNU/Linux + +Follow the official documentation to install: +- [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/install-ubuntu) +- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux) +- [Helm](https://helm.sh/docs/intro/install/) +- kubectl(depends on your system) + +You can install the mosquitto clients by running: +`sudo apt install mosquitto-clients` + +## Changes since Azure IoT Operations public preview + +- Additional test scripts have been added to demonstrate the capabilities of the Azure IoT Operations media connector. +- Now using PowerShell scripts instead of Polyglot notebooks. + +## Limitations + +The Azure IoT Operations media connector has the following limitations: + +- No discovery, this will be implemented by the ONVIF connector, currently under development. +- Limits on the number of concurrent connections and the file system use are not enforced. +- Performance and footprint are not optimized. +- The mRPC API is not publicly documented yet and is subject to change. + +## Description of package contents: + +- **README.md**: This file. +- **Overview.md**: General information about Azure IoT Operations and the Azure IoT Operations media connector. +- **media-connector-demo.mermaid and produced .png and .svg**: Diagram of the demo environment. +- **Broker listener (broker-listener/)**: This folder contains PowerShell scripts and kuberentes resources that show how to deploy an open (non-TLS) listener for MQ. +- **Media Server (media-server/)**: This folder contains scripts and yaml files that demonstrates how to deploy a media server in a kubernetes cluster. +- **resources/aep-*.yaml**: Example Asset Endpoint Profiles (AEPs) that can be used to configure the media connector. +- **resources/asset-*.yaml**: Example assets that can be used to configure the media connector. +- **Install-ResourceFile.ps1**: This PowerShell script installs a kubernetes resource file for the Azure IoT Operations media connector. +- **Uninstall-ResourceFile.ps1**: This PowerShell script uninstalls a kubernetes resource file for the Azure IoT Operations media connector. +- **Invoke-Test*.ps1**: These PowerShell scripts run different test scenarios for the Azure IoT Operations media connector. +- **Start-InteractiveSession.ps1**: This PowerShell script starts an interactive session in the Azure IoT Operations media connector container. +- **Start-MqttListener.ps1**: This PowerShell script starts an MQTT listener on the Azure IoT Operations MQTT broker. +- **Start-FileSystemMonitor.ps1**: This PowerShell script start monitoring for file changes on the Azure IoT Operations media connector container. +- **Start-RtspStreamViewer.ps1**: This PowerShell script start the default browser to look at streaming RTPS from the default media server. diff --git a/samples/media-connector-invoke-test/Start-FileSystemMonitor.ps1 b/samples/media-connector-invoke-test/Start-FileSystemMonitor.ps1 new file mode 100644 index 0000000..599531a --- /dev/null +++ b/samples/media-connector-invoke-test/Start-FileSystemMonitor.ps1 @@ -0,0 +1,50 @@ +#Requires -Version 7 +<# + Start a file monitor session in the AIO Media Connector pod. +#> +param ( + [Parameter( + HelpMessage="The path to monitor.")] + [string]$pathToMonitor = "" +) + +Write-Host (Split-Path -Path $PSCommandPath -Leaf).ToUpper() -ForegroundColor White + +. (Join-Path $PSScriptRoot "Test-Prerequisites.ps1") + +$aioNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +If ($pathToMonitor -eq "") { + $pathToMonitor = "/tmp/${aioNamespace}" +} +Write-Host "Path to monitor: $pathToMonitor" + +$podName = (kubectl get pods -n $aioConnectorsNamespace -l app.kubernetes.io/component=aio-opc-media-1 --output=jsonpath='{.items[*].metadata.name}') +if ($null -eq $podName) { + Write-Host "No pod found" + Exit 1 +} +Write-Host "Pod name: $podName" + +try { + Write-Host "Checking if inotifywait is installed..." + $iNotifyWaitPath = "/usr/bin/inotifywait" + $commandString = "kubectl exec --stdin --tty $podName -n $aioConnectorsNamespace -- ls ${iNotifyWaitPath}" + $result = Invoke-Expression "${commandString}" + If ($result -eq $iNotifyWaitPath) { + Write-Host "Starting the file system monitor based on inotifywait..." + $commandString = "kubectl exec --stdin --tty $podName -n $aioConnectorsNamespace -- inotifywait -m -r -e create -e delete -e modify --timefmt `"%Y-%m-%d %H:%M:%S`" --format `"[%T] [%e] [%w] [%f]`" ${pathToMonitor}" + Invoke-Expression "${commandString}" + } Else { + Write-Host "inotifywait is not installed, pooling with find..." + $commandString = "kubectl exec --stdin --tty $podName -n $aioConnectorsNamespace -- sh -c `'while true ; do find ${pathToMonitor} -cmin 0.05 ; sleep 3 ; done `'" + Invoke-Expression "${commandString}" + } + +} finally { + Write-Host "`nThe file system monitor ended." +} diff --git a/samples/media-connector-invoke-test/Start-MqttListener.ps1 b/samples/media-connector-invoke-test/Start-MqttListener.ps1 new file mode 100644 index 0000000..88309f7 --- /dev/null +++ b/samples/media-connector-invoke-test/Start-MqttListener.ps1 @@ -0,0 +1,46 @@ +#Requires -Version 7 +<# + Start a an MQTT listener using mosquitto_sub. +#> +param ( + [Parameter( + HelpMessage="The listen topic.")] + [string[]]$listenTopics = @(), + [Parameter( + HelpMessage="The format string to be used to print messages.")] + [string]$printFormat = "Topic [%t], ID [%m], QoS [%q], Retain [%r], Size [%l]" +) + +Write-Host (Split-Path -Path $PSCommandPath -Leaf).ToUpper() -ForegroundColor White + +. (Join-Path $PSScriptRoot "Test-Prerequisites.ps1") + +. (Join-Path $PSScriptRoot "Update-AioBrokerEndpointFile.ps1") + +$aioNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioMqHost = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_broker_host") -Raw).Trim() +Write-Host "AIO MQ host: $aioMqHost" + +$aioMqPort = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_broker_port") -Raw).Trim() +Write-Host "AIO MQ port: $aioMqPort" + +If ($listenTopics.Count -eq 0) { + $listenTopics = @("${aioNamespace}/#") +} +Write-Host "listenTopics: $listenTopics" + +Write-Host "printFormat: $printFormat" + +ForEach ($listenTopic in $listenTopics) { + $listenTopicParams += " -t `"${listenTopic}`" " +} + +try { + Write-Host "Starting the mosquitto_sub process..." + $commandString = "mosquitto_sub --host $aioMqHost --port $aioMqPort --verbose -V mqttv5 -F `"${printFormat}`" ${listenTopicParams}" + Invoke-Expression "${commandString}" +} finally { + Write-Host "`nThe mosquitto_sub process ended." +} diff --git a/samples/media-connector-invoke-test/Start-RtspStreamViewer.ps1 b/samples/media-connector-invoke-test/Start-RtspStreamViewer.ps1 new file mode 100644 index 0000000..dc265aa --- /dev/null +++ b/samples/media-connector-invoke-test/Start-RtspStreamViewer.ps1 @@ -0,0 +1,63 @@ +#Requires -Version 7 +<# + Start the default browser to watch an RTPS stream from the media server. +#> +param ( + [Parameter( + Mandatory, + HelpMessage="The asset name.")] + [string]$assetName = "" +) + +Write-Host (Split-Path -Path $PSCommandPath -Leaf).ToUpper() -ForegroundColor White + +. (Join-Path $PSScriptRoot "Test-Prerequisites.ps1") + +. (Join-Path $PSScriptRoot "Update-MediaServerConfigFiles.ps1") + +$aioNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$mediaServer = (Get-Content -Path (Join-Path $PSScriptRoot ".config_media_server_host") -Raw).Trim() +Write-Host "Media Server: $mediaServer" + +Write-Host "Asset Name: $assetName" + +$streamUrl = "http://${mediaServer}:8888/${aioConnectorsNamespace}/data/${assetName}/" +Write-Host "Stream URL: $streamUrl" + +Write-Host "Showing the RTSP stream from the media server in the default browser..." + +if ($PSVersionTable.PSEdition -eq "Core") { + # Check if the script is running on Windows + If ([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Windows)) { + Write-Host "Running on Windows" + . start $streamUrl + } + # Check if the script is running on Linux + ElseIf ([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Linux)) { + Write-Host "Running on Linux" + If (Test-Path -Path env:WSL_DISTRO_NAME) { + Write-Host "Running on WSL" + . wslview $streamUrl + } Else { + Write-Host "Not running on WSL" + . xdg-open $streamUrl + } + } + # Check if the script is running on macOS + ElseIf ([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::OSX)) { + Write-Host "Running on macOS" + + Throw 'Error: macOS is not (yet) supported.`n' + } Else { + Write-Host "Unknown platform" + + Throw 'Error: Unknown platform.`n' + } +} else { + Write-Host "This script requires PowerShell Core" +} diff --git a/samples/media-connector-invoke-test/Test-Prerequisites.ps1 b/samples/media-connector-invoke-test/Test-Prerequisites.ps1 new file mode 100644 index 0000000..898c5b5 --- /dev/null +++ b/samples/media-connector-invoke-test/Test-Prerequisites.ps1 @@ -0,0 +1,52 @@ +#Requires -Version 7 +<# + Testing the prerequisites for the scripts in this package. +#> + +Write-Host "Testing the prerequisites..." + +If ($PSScriptRoot -match " ") { + Throw "Error: The script path contains spaces." + Exit 1 +} Else { + Write-Host "The script path does not contain spaces!" +} + +Write-Host "Checking for kubectl..." +If (-not (Get-Command -Name "kubectl" -ErrorAction SilentlyContinue)) { + Throw "Error: kubectl not found, make sure it is installed and accessible." + Exit 1 +} Else { + Write-Host "kubectl found!" +} + +Write-Host "Checking for mosquitto_pub..." +If (-not (Get-Command -Name "mosquitto_pub" -ErrorAction SilentlyContinue)) { + Throw "Error: mosquitto_pub not found, make sure it is installed and accessible." + Exit 1 +} Else { + Write-Host "mosquitto_pub found!" +} + +Write-Host "Checking for mosquitto_sub..." +If (-not (Get-Command -Name "mosquitto_sub" -ErrorAction SilentlyContinue)) { + Throw "Error: mosquitto_sub not found, make sure it is installed and accessible." + Exit 1 +} Else { + Write-Host "mosquitto_sub found!" +} + +Write-Host "Checking if a default cluster is configured..." +# Define the command to get the current kubectl context +$kubectlContextCommand = "kubectl config current-context" +# Execute the command and capture the output +$currentContext = Invoke-Expression $kubectlContextCommand +# Check if the output is empty +if ([string]::IsNullOrWhiteSpace($currentContext)) { + Throw "No Kubernetes cluster is currently configured." + Exit 1 +} else { + Write-Host "Current Kubernetes context: $currentContext" +} + +Write-Host "Prerequisites are met!`n" diff --git a/samples/media-connector-invoke-test/Uninstall-ResourceFile.ps1 b/samples/media-connector-invoke-test/Uninstall-ResourceFile.ps1 new file mode 100644 index 0000000..55cad75 --- /dev/null +++ b/samples/media-connector-invoke-test/Uninstall-ResourceFile.ps1 @@ -0,0 +1,34 @@ +#Requires -Version 7 +<# + Uninstall a resource file. +#> +param ( + [Parameter( + Mandatory=$true, + HelpMessage="The resource file.")] + [string]$resourceFile +) + +Write-Host "`n" +Write-Host (Split-Path -Path $PSCommandPath -Leaf).ToUpper() -ForegroundColor White + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path $PSScriptRoot ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$resourcesDirectory = (Get-Content -Path (Join-Path $PSScriptRoot ".config_resources_path") -Raw).Trim() +$resourcesDirectory = $ExecutionContext.InvokeCommand.ExpandString(${resourcesDirectory}) +Write-Host "Resources directory: $resourcesDirectory" + +Write-Host "Resource file: $resourceFile" + +$fileFullPath=(Join-Path $resourcesDirectory $resourceFile) +Write-Host "Resource file full path: ${fileFullPath}" + +Write-Host "Deleteing the resource..." +. kubectl delete -n ${aioConnectorsNamespace} -f ${fileFullPath} +If ($LastExitCode -ne 0) { + Write-Host "Error: The resource could not be applied." + Exit $LastExitCode +} Else { + Write-Host "The resource was deleted successfully.`n" +} diff --git a/samples/media-connector-invoke-test/Update-AioBrokerEndpointFile.ps1 b/samples/media-connector-invoke-test/Update-AioBrokerEndpointFile.ps1 new file mode 100644 index 0000000..5afe992 --- /dev/null +++ b/samples/media-connector-invoke-test/Update-AioBrokerEndpointFile.ps1 @@ -0,0 +1,78 @@ +#Requires -Version 7 +<# + Update the AIO Broker endpoint file. +#> + +$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath .config_aio_namespace) -Raw).Trim() +Write-Host "AIO connectors namespace: ${aioNamespace}" + +$aioMqPort=1883 # Default MQTT port + +Function Detect-Broker { + Param ( + [string]$serviceName + ) + + Write-Host "Detecting the AIO Broker endpoint with service name $serviceName..." + + $aioMqEndpointIp=(kubectl get service $serviceName ` + --namespace ${aioNamespace} ` + --output jsonpath='{.status.loadBalancer.ingress[0].ip}') + If (${aioMqEndpointIp}) { + Write-Host "AIO Broker endpoint IP: ${aioMqEndpointIp}" + + $aioMqPort=(kubectl get service $serviceName ` + --namespace ${aioNamespace} ` + --output jsonpath='{.spec.ports[0].port}') + Write-Host "AIO Broker port: ${aioMqPort}" + + $aioMqEndpoint="mqtt://${aioMqEndpointIp}:${aioMqPort}" + $aioMqHost=$aioMqEndpointIp + } Else { + $aioMqEndpointHostname=(kubectl get service $serviceName ` + --namespace ${aioNamespace} ` + --output jsonpath='{.status.loadBalancer.ingress[0].hostname}') + If (${aioMqEndpointHostname}) { + Write-Host "AIO Broker endpoint hostname: ${aioMqEndpointHostname}" + + $aioMqPort=(kubectl get service $serviceName ` + --namespace ${aioNamespace} ` + --output jsonpath='{.spec.ports[0].port}') + + $aioMqEndpoint="mqtt://${aioMqEndpointHostname}:${aioMqPort}" + $aioMqHost=$aioMqEndpointHostname + } + } +} + +$endpointNames = @( + "aio-broker", + "aio-broker-listener-non-tls", + "aio-broker-notls" +) + +ForEach ($endpointName in $endpointNames) { + + . Detect-Broker -serviceName $endpointName + + If (${aioMqEndpointIp} -or ${aioMqEndpointHostname}) { + Write-Host "AIO Broker endpoint detected!" + Break + } +} + +If (-not ${aioMqEndpointIp} -and -not ${aioMqEndpointHostname}) { + Throw "Failed to detect the AIO Broker endpoint." + Exit 1 +} + +Write-Host "AIO Broker endpoint: ${aioMqEndpoint}" +Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_broker_endpoint") -InputObject $aioMqEndpoint -NoNewline + +Write-Host "AIO Broker host: ${aioMqHost}" +Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_broker_host") -InputObject $aioMqHost -NoNewline + +Write-Host "AIO Broker port: ${aioMqPort}" +Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_broker_port") -InputObject $aioMqPort -NoNewline + +Write-Host "Done!`n" diff --git a/samples/media-connector-invoke-test/Update-MediaServerConfigFiles.ps1 b/samples/media-connector-invoke-test/Update-MediaServerConfigFiles.ps1 new file mode 100644 index 0000000..4ff18a1 --- /dev/null +++ b/samples/media-connector-invoke-test/Update-MediaServerConfigFiles.ps1 @@ -0,0 +1,32 @@ +#Requires -Version 7 +<# + Update the Media Server config files. +#> + +$mediaServerNamespace="media-server" + +Write-Host "Detecting the Media Server endpoint..." +$mediaServerEndpointIp=(kubectl get service media-server-public ` + --namespace ${mediaServerNamespace} ` + --output jsonpath='{.status.loadBalancer.ingress[0].ip}') +If (${mediaServerEndpointIp}) { + Write-Host "Media Server endpoint IP: ${mediaServerEndpointIp}" + $mediaServerHost=$mediaServerEndpointIp +} Else { + $mediaServerEndpointHostname=(kubectl get service media-server-public ` + --namespace ${mediaServerNamespace} ` + --output jsonpath='{.status.loadBalancer.ingress[0].hostname}') + If (${mediaServerEndpointHostname}) { + Write-Host "Media Server endpoint hostname: ${mediaServerEndpointHostname}" + $mediaServerHost=$mediaServerEndpointHostname + } +} +If (-not ${mediaServerEndpointIp} -and -not ${mediaServerEndpointHostname}) { + Write-Host "Failed to detect the Media Server endpoint. Exiting..." + Exit 1 +} + +Write-Host "Media Server host: ${mediaServerHost}" +Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ".config_media_server_host") -InputObject $mediaServerHost -NoNewline + +Write-Host "Done!`n" diff --git a/samples/media-connector-invoke-test/broker-listener/Install-BrokerListener.ps1 b/samples/media-connector-invoke-test/broker-listener/Install-BrokerListener.ps1 new file mode 100644 index 0000000..2953b53 --- /dev/null +++ b/samples/media-connector-invoke-test/broker-listener/Install-BrokerListener.ps1 @@ -0,0 +1,19 @@ +<# +.SYNOPSIS + Deploy an open (non-TLS) broker listener into the default Kubernetes cluster. +.DESCRIPTION + This PowerShell script deploys an open (non-TLS) broker listener into the default Kubernetes cluster using kubectl. +.LINK + https://azure.com/ +.NOTES + (c) 2024 Microsoft Corporation. All rights reserved. + Author: andrejm@microsoft.com +#> + +try { + & kubectl apply -f broker-listener.yaml --validate=false + exit 0 # success +} catch { + "⚠️ Error in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])" + exit 1 +} diff --git a/samples/media-connector-invoke-test/broker-listener/Uninstall-BrokerListener.ps1 b/samples/media-connector-invoke-test/broker-listener/Uninstall-BrokerListener.ps1 new file mode 100644 index 0000000..d84c64f --- /dev/null +++ b/samples/media-connector-invoke-test/broker-listener/Uninstall-BrokerListener.ps1 @@ -0,0 +1,19 @@ +<# +.SYNOPSIS + Deletes an open (non-TLS) broker listener from the default Kubernetes cluster. +.DESCRIPTION + This PowerShell script deletes an open (non-TLS) broker listener from the default Kubernetes cluster using kubectl. +.LINK + https://azure.com/ +.NOTES + (c) 2024 Microsoft Corporation. All rights reserved. + Author: andrejm@microsoft.com +#> + +try { + & kubectl delete -f broker-listener.yaml + exit 0 # success +} catch { + "⚠️ Error in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])" + exit 1 +} diff --git a/samples/media-connector-invoke-test/broker-listener/broker-listener.yaml b/samples/media-connector-invoke-test/broker-listener/broker-listener.yaml new file mode 100644 index 0000000..9f92e45 --- /dev/null +++ b/samples/media-connector-invoke-test/broker-listener/broker-listener.yaml @@ -0,0 +1,24 @@ +apiVersion: mqttbroker.iotoperations.azure.com/v1 +kind: BrokerListener +metadata: + name: aio-broker-notls + namespace: azure-iot-operations +spec: + brokerRef: default + serviceType: LoadBalancer + ports: + - port: 1883 + protocol: Mqtt + +--- + +apiVersion: v1 +kind: Service +metadata: + name: aio-broker-notls + namespace: azure-iot-operations +spec: + type: LoadBalancer + ports: + - port: 1883 + targetPort: 1883 diff --git a/samples/media-connector-invoke-test/media-connector-demo.png b/samples/media-connector-invoke-test/media-connector-demo.png new file mode 100644 index 0000000..f3b145c Binary files /dev/null and b/samples/media-connector-invoke-test/media-connector-demo.png differ diff --git a/samples/media-connector-invoke-test/media-connector-demo.svg b/samples/media-connector-invoke-test/media-connector-demo.svg new file mode 100644 index 0000000..8f71929 --- /dev/null +++ b/samples/media-connector-invoke-test/media-connector-demo.svg @@ -0,0 +1 @@ +AzureAIOAzure CloudRTSPHTTPRTSP, RTCP, MPEG-TS, ...RTSP, RTCP, MPEG-TS, SRT, ...RTSP, RTCP, MPEG-TS, SRT, ...HTTP/HTTPSSnapshotsFilesClipsFilesTelemetrySnapshotsMessagesStreamsRTSPHLSRTSP, RTCP, SRT, HLSRTSP, RTCP, SRTHLSFilesFilesRTSPVideo Indexer EdgeFabricAzure StorageVideo Indexer CloudMedia ConnectorFile System and/or VolumeEdge Storage AcceleratorBrokerTinyKubeExample AEP/AssetCameraMedia SourceMedia Server - ServerMedia PusherWeb ServerVLCFFplayWeb Browser \ No newline at end of file diff --git a/samples/media-connector-invoke-test/media-server/Install-MediaServer.ps1 b/samples/media-connector-invoke-test/media-server/Install-MediaServer.ps1 new file mode 100644 index 0000000..e66667b --- /dev/null +++ b/samples/media-connector-invoke-test/media-server/Install-MediaServer.ps1 @@ -0,0 +1,28 @@ +<# +.SYNOPSIS + Deploy MediaMTX into the default Kubernetes cluster. +.DESCRIPTION + This PowerShell script deploys MediaMTX into the default Kubernetes cluster using kubectl. +.EXAMPLE + PS> ./media-server-deploy.ps1 + namespace/media-server created + deployment.apps/media-server created + service/media-server created + service/media-server-public created +.LINK + https://azure.com/ +.NOTES + (c) 2024 Microsoft Corporation. All rights reserved. + Author: andrejm@microsoft.com +#> + +try { + & kubectl create namespace media-server --dry-run=client -o yaml | kubectl apply -f - + & kubectl apply -f media-server-deployment.yaml --validate=false + & kubectl apply -f media-server-service.yaml --validate=false + & kubectl apply -f media-server-service-public.yaml --validate=false + exit 0 # success +} catch { + "⚠️ Error in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])" + exit 1 +} diff --git a/samples/media-connector-invoke-test/media-server/README.md b/samples/media-connector-invoke-test/media-server/README.md new file mode 100644 index 0000000..ea9faf8 --- /dev/null +++ b/samples/media-connector-invoke-test/media-server/README.md @@ -0,0 +1,17 @@ +The scripts in this directory help in installing, uninstalling, and managing a media server. + +The scripts are written in PowerShell and use the kubectl to interact with the cluster. + +The scripts are designed to be run on Windows and Linux. + +## Prerequisites + +- [kubectl](installation instructions: https://kubernetes.io/docs/tasks/tools/install-kubectl/) + +## Usage + +1. Open a PowerShell terminal. +2. Check the prerequisites: `pwsh Test-Prerequisites.ps1`. +3. Install the Media Server: `pwsh Install-MediaServer.ps1` +4. Check the Media Server after installation: `pwsh Test-MediaServer.ps1` +5. When you are done, uninstall the Media Server: `pwsh Uninstall-MediaServer.ps1` diff --git a/samples/media-connector-invoke-test/media-server/Test-MediaServer.ps1 b/samples/media-connector-invoke-test/media-server/Test-MediaServer.ps1 new file mode 100644 index 0000000..b899dc8 --- /dev/null +++ b/samples/media-connector-invoke-test/media-server/Test-MediaServer.ps1 @@ -0,0 +1,24 @@ +$mediaServerNamespace="media-server" + +Write-Host "Detecting the Media Server endpoint..." +$mediaServerEndpointIp=(kubectl get service media-server-public ` + --namespace ${mediaServerNamespace} ` + --output jsonpath='{.status.loadBalancer.ingress[0].ip}') +If (${mediaServerEndpointIp}) { + Write-Host "Media Server endpoint IP: ${mediaServerEndpointIp}" + $mediaServerHost=$mediaServerEndpointIp +} Else { + $mediaServerEndpointHostname=(kubectl get service media-server-public ` + --namespace ${mediaServerNamespace} ` + --output jsonpath='{.status.loadBalancer.ingress[0].hostname}') + If (${mediaServerEndpointHostname}) { + Write-Host "Media Server endpoint hostname: ${mediaServerEndpointHostname}" + $mediaServerHost=$mediaServerEndpointHostname + } +} +If (-not ${mediaServerEndpointIp} -and -not ${mediaServerEndpointHostname}) { + Write-Host "Failed to detect the Media Server endpoint. Exiting..." + Exit 1 +} + +Write-Host "Media Server detected, host: ${mediaServerHost}" diff --git a/samples/media-connector-invoke-test/media-server/Test-Prerequisites.ps1 b/samples/media-connector-invoke-test/media-server/Test-Prerequisites.ps1 new file mode 100644 index 0000000..e571923 --- /dev/null +++ b/samples/media-connector-invoke-test/media-server/Test-Prerequisites.ps1 @@ -0,0 +1,11 @@ +Write-Host "Testing the prerequisites..." + +Write-Host "Checking for kubectl..." +If (-not (Get-Command -Name "kubectl" -ErrorAction SilentlyContinue)) { + Write-Host "Error: kubectl not found, make sure it is installed and accessible" + Exit 1 +} Else { + Write-Host "kubectl found!" +} + +Write-Host "Done!`n" diff --git a/samples/media-connector-invoke-test/media-server/Uninstall-MediaServer.ps1 b/samples/media-connector-invoke-test/media-server/Uninstall-MediaServer.ps1 new file mode 100644 index 0000000..4ab5ac3 --- /dev/null +++ b/samples/media-connector-invoke-test/media-server/Uninstall-MediaServer.ps1 @@ -0,0 +1,24 @@ +<# +.SYNOPSIS + Deploy MediaMTX into the default Kubernetes cluster. +.DESCRIPTION + This PowerShell script deploys MediaMTX into the default Kubernetes cluster using kubectl. +.EXAMPLE + PS> ./media-server-delete.ps1 +.LINK + https://azure.com/ +.NOTES + (c) 2024 Microsoft Corporation. All rights reserved. + Author: andrejm@microsoft.com +#> + +try { + & kubectl delete -f media-server-service-public.yaml + & kubectl delete -f media-server-service.yaml + & kubectl delete -f media-server-deployment.yaml + & kubectl delete namespace media-server + exit 0 # success +} catch { + "⚠️ Error in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])" + exit 1 +} diff --git a/samples/media-connector-invoke-test/resources/aep-public-http-anonymous-1.yaml b/samples/media-connector-invoke-test/resources/aep-public-http-anonymous-1.yaml index 1d4ac3a..be53dea 100644 --- a/samples/media-connector-invoke-test/resources/aep-public-http-anonymous-1.yaml +++ b/samples/media-connector-invoke-test/resources/aep-public-http-anonymous-1.yaml @@ -7,7 +7,7 @@ spec: { "$schema": "https://aiobrokers.blob.core.windows.net/aio-media-connector/1.0.0.json" } - endpointProfileType: Media + endpointProfileType: Microsoft.Media targetAddress: http://s7d2.scene7.com/is/content/microsoftcorp/CLO24-Azure-Retail-16x9 authentication: method: Anonymous diff --git a/samples/media-connector-invoke-test/resources/aep-public-https-anonymous-1.yaml b/samples/media-connector-invoke-test/resources/aep-public-https-anonymous-1.yaml index e2d799d..c822333 100644 --- a/samples/media-connector-invoke-test/resources/aep-public-https-anonymous-1.yaml +++ b/samples/media-connector-invoke-test/resources/aep-public-https-anonymous-1.yaml @@ -7,7 +7,7 @@ spec: { "$schema": "https://aiobrokers.blob.core.windows.net/aio-media-connector/1.0.0.json" } - endpointProfileType: Media + endpointProfileType: Microsoft.Media targetAddress: https://s7d2.scene7.com/is/content/microsoftcorp/CLO24-Azure-Retail-16x9 authentication: method: Anonymous diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-autostart.yaml index 87c79b1..041d9af 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-clip-to-fs-autostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-noautostart.yaml index 0e5d18f..7c99d2f 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-fs-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-clip-to-fs-noautostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-autostart.yaml index 5c2e273..f057f8b 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-clip-to-mqtt-autostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-noautostart.yaml index 6acea54..072124f 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-clip-to-mqtt-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-clip-to-mqtt-noautostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-hls-to-fs-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-hls-to-fs-autostart.yaml new file mode 100644 index 0000000..3322858 --- /dev/null +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-hls-to-fs-autostart.yaml @@ -0,0 +1,20 @@ +apiVersion: deviceregistry.microsoft.com/v1 +kind: Asset +metadata: + name: asset-public-http-anonymous-1-hls-to-fs-autostart +spec: + assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true + datasets: + - name: dataset1 + dataPoints: + - name: hls-to-fs + dataSource: hls-to-fs + dataPointConfiguration: |- + { + "taskType": "hls-to-fs", + "autostart": true, + "realtime": true, + "loop": true, + "duration": 3 + } diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-autostart.yaml index 883e6ac..047e6c5 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-snapshot-to-fs-autostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-noautostart.yaml index 014f401..a714aa3 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-fs-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-snapshot-to-fs-noautostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-autostart.yaml index da6fe69..11f724c 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-snapshot-to-mqtt-autostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-noautostart.yaml index ffa7968..e45c562 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-snapshot-to-mqtt-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-snapshot-to-mqtt-noautostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-autostart.yaml index e48fc4f..8886f2b 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-stream-to-rtsp-autostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-noautostart.yaml index 9ab60c5..7ea765e 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-http-anonymous-1-stream-to-rtsp-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-http-anonymous-1-stream-to-rtsp-noautostart spec: assetEndpointProfileRef: aep-public-http-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-autostart.yaml index 5d2d823..00b143b 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-clip-to-fs-autostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-noautostart.yaml index 34092ca..b6d68e4 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-fs-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-clip-to-fs-noautostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-autostart.yaml index 58b4f9e..5083757 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-clip-to-mqtt-autostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-noautostart.yaml index 0bede92..4caaba2 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-clip-to-mqtt-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-clip-to-mqtt-noautostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-autostart.yaml index 6597fd1..eb6e5e2 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-snapshot-to-fs-autostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-noautostart.yaml index 761dc32..4de000a 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-fs-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-snapshot-to-fs-noautostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-autostart.yaml index 437d904..6a62ba7 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-snapshot-to-mqtt-autostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-noautostart.yaml index 5578e54..29ba736 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-snapshot-to-mqtt-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-snapshot-to-mqtt-noautostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-autostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-autostart.yaml index 8d768de..994aa06 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-autostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-autostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-stream-to-rtsp-autostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-noautostart.yaml b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-noautostart.yaml index 14600ba..df8bd09 100644 --- a/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-noautostart.yaml +++ b/samples/media-connector-invoke-test/resources/asset-public-https-anonymous-1-stream-to-rtsp-noautostart.yaml @@ -4,6 +4,7 @@ metadata: name: asset-public-https-anonymous-1-stream-to-rtsp-noautostart spec: assetEndpointProfileRef: aep-public-https-anonymous-1 + enabled: true datasets: - name: dataset1 dataPoints: diff --git a/samples/media-connector-invoke-test/update-aio/Update-AioMediaConnector.ps1 b/samples/media-connector-invoke-test/update-aio/Update-AioMediaConnector.ps1 new file mode 100644 index 0000000..8af93f8 --- /dev/null +++ b/samples/media-connector-invoke-test/update-aio/Update-AioMediaConnector.ps1 @@ -0,0 +1,38 @@ +#Requires -Version 7 +<# + Uninstall a resource file. +#> +param ( + [Parameter( + Mandatory=$true, + HelpMessage="The cluster resource group.")] + [string]$clusterResourceGroup, + [Parameter( + Mandatory=$true, + HelpMessage="The cluster name.")] + [string]$clusterName, + [Parameter( + HelpMessage="The media connector version to use.")] + [string]$mediaConnectorVersion = "1.1.0" +) + +$extension = az k8s-extension list ` + --cluster-name $clusterName ` + --cluster-type connectedClusters ` + --resource-group $clusterResourceGroup ` + --query "[?extensionType == 'microsoft.iotoperations']" ` + | ConvertFrom-Json + +az k8s-extension update ` + --version $extension.version ` + --name $extension.name ` + --release-train $extension.releaseTrain ` + --cluster-name $clusterName ` + --resource-group $clusterResourceGroup ` + --cluster-type connectedClusters ` + --auto-upgrade-minor-version false ` + --config connectors.image.registry=mcr.microsoft.com ` + --config connectors.image.repository=aio-connectors/helmchart/microsoft-aio-connectors ` + --config connectors.image.tag=$mediaConnectorVersion ` + --config connectors.values.enablePreviewFeatures=true ` + --yes