From 97a02eb68725e748dddcb516539d4223f82a0f98 Mon Sep 17 00:00:00 2001 From: Dominic Betts <1454644+dominicbetts@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:05:53 +0000 Subject: [PATCH] Update media connector sample --- .../aio-onvif-connector-ptz-demo/README.md | 11 +- .../.config_aio_connectors_namespace | 1 + .../.config_aio_namespace | 1 + .../.config_resources_path | 1 + .../Install-ResourceFile.ps1 | 34 ++++++ .../Invoke-GetTaskDebugInfo.ps1 | 22 ++++ .../Invoke-GetTaskErrorString.ps1 | 22 ++++ .../Invoke-GetTaskOutputString.ps1 | 22 ++++ .../Invoke-GetTaskState.ps1 | 22 ++++ ...oke-ResourceInstallMonitorAndUninstall.ps1 | 60 +++++++++++ .../Invoke-TestClipToFsAutostart.ps1 | 20 ++++ .../Invoke-TestClipToMqttAutostart.ps1 | 18 ++++ .../Invoke-TestSnapshotToFsAutostart.ps1 | 20 ++++ .../Invoke-TestSnapshotToMqttAutostart.ps1 | 20 ++++ .../Invoke-TestStreamToRtspAutostart.ps1 | 21 ++++ samples/media-connector-invoke-test/README.md | 98 +++++++++++++++++- .../Start-FileSystemMonitor.ps1 | 50 +++++++++ .../Start-InteractiveSession.ps1 | 27 +++++ .../Start-MqttListener.ps1 | 46 ++++++++ .../Start-RtspStreamViewer.ps1 | 63 +++++++++++ .../Test-Prerequisites.ps1 | 52 ++++++++++ .../Uninstall-ResourceFile.ps1 | 34 ++++++ .../Update-AioMqEndpointFile.ps1 | 54 ++++++++++ .../Update-MediaServerConfigFiles.ps1 | 32 ++++++ .../Install-BrokerListener.ps1 | 19 ++++ .../Uninstall-BrokerListener.ps1 | 19 ++++ .../broker-listener/broker-listener.yaml | 12 +++ .../media-connector-demo.png | Bin 0 -> 124731 bytes .../media-server/Install-MediaServer.ps1 | 28 +++++ .../media-server/README.md | 15 +++ .../media-server/Test-MediaServer.ps1 | 24 +++++ .../media-server/Test-Prerequisites.ps1 | 11 ++ .../media-server/Uninstall-MediaServer.ps1 | 24 +++++ 33 files changed, 893 insertions(+), 10 deletions(-) create mode 100644 samples/media-connector-invoke-test/.config_aio_connectors_namespace create mode 100644 samples/media-connector-invoke-test/.config_aio_namespace create mode 100644 samples/media-connector-invoke-test/.config_resources_path create mode 100644 samples/media-connector-invoke-test/Install-ResourceFile.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-GetTaskDebugInfo.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-GetTaskErrorString.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-GetTaskOutputString.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-GetTaskState.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-ResourceInstallMonitorAndUninstall.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-TestClipToFsAutostart.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-TestClipToMqttAutostart.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-TestSnapshotToFsAutostart.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-TestSnapshotToMqttAutostart.ps1 create mode 100644 samples/media-connector-invoke-test/Invoke-TestStreamToRtspAutostart.ps1 create mode 100644 samples/media-connector-invoke-test/Start-FileSystemMonitor.ps1 create mode 100644 samples/media-connector-invoke-test/Start-InteractiveSession.ps1 create mode 100644 samples/media-connector-invoke-test/Start-MqttListener.ps1 create mode 100644 samples/media-connector-invoke-test/Start-RtspStreamViewer.ps1 create mode 100644 samples/media-connector-invoke-test/Test-Prerequisites.ps1 create mode 100644 samples/media-connector-invoke-test/Uninstall-ResourceFile.ps1 create mode 100644 samples/media-connector-invoke-test/Update-AioMqEndpointFile.ps1 create mode 100644 samples/media-connector-invoke-test/Update-MediaServerConfigFiles.ps1 create mode 100644 samples/media-connector-invoke-test/broker-listener/Install-BrokerListener.ps1 create mode 100644 samples/media-connector-invoke-test/broker-listener/Uninstall-BrokerListener.ps1 create mode 100644 samples/media-connector-invoke-test/broker-listener/broker-listener.yaml create mode 100644 samples/media-connector-invoke-test/media-connector-demo.png create mode 100644 samples/media-connector-invoke-test/media-server/Install-MediaServer.ps1 create mode 100644 samples/media-connector-invoke-test/media-server/README.md create mode 100644 samples/media-connector-invoke-test/media-server/Test-MediaServer.ps1 create mode 100644 samples/media-connector-invoke-test/media-server/Test-Prerequisites.ps1 create mode 100644 samples/media-connector-invoke-test/media-server/Uninstall-MediaServer.ps1 diff --git a/samples/aio-onvif-connector-ptz-demo/README.md b/samples/aio-onvif-connector-ptz-demo/README.md index b7b1682..4db4b3f 100644 --- a/samples/aio-onvif-connector-ptz-demo/README.md +++ b/samples/aio-onvif-connector-ptz-demo/README.md @@ -72,7 +72,7 @@ kubectl apply -f aep.yaml To create a PTZ asset assigned to the asset endpoint you created in the previous step, create a file called *asset.yaml* with the following content: -```yaml +```yaml apiVersion: deviceregistry.microsoft.com/v1 kind: Asset metadata: @@ -171,11 +171,12 @@ Create a file called *broker-listener.yaml* with the following content: apiVersion: mqttbroker.iotoperations.azure.com/v1 kind: BrokerListener metadata: - name: test-listener + name: aio-broker-listener-non-tls namespace: azure-iot-operations spec: brokerRef: default serviceType: LoadBalancer + serviceName: aio-broker-listener-non-tls ports: - port: 1883 protocol: Mqtt @@ -194,7 +195,7 @@ kubectl apply -f broker-listener.yaml -n azure-iot-operations Update the Azure IoT Operations configuration to use the broker listener you created in the previous step: ```bash -kubectl set env deployment/aio-opc-supervisor opcuabroker_MqttOptions__MqttBroker=mqtt://test-listener.azure-iot-operations:1883 opcuabroker_MqttOptions__AuthenticationMethod=None -n azure-iot-operations +kubectl set env deployment/aio-opc-supervisor opcuabroker_MqttOptions__MqttBroker=mqtt://aio-broker-listener-non-tls.azure-iot-operations:1883 opcuabroker_MqttOptions__AuthenticationMethod=None -n azure-iot-operations ``` ### Port forward the broker listener @@ -202,7 +203,7 @@ kubectl set env deployment/aio-opc-supervisor opcuabroker_MqttOptions__MqttBroke Port forward the broker listener to your local machine in a second terminal: ```bash -kubectl port-forward svc/test-listener -n azure-iot-operations 1883:1883 +kubectl port-forward svc/aio-broker-listener-non-tls -n azure-iot-operations 1883:1883 ``` Leave this shell open to keep the port forward active. @@ -230,6 +231,6 @@ To remove the resources created in the previous steps and restore the configurat kubectl delete secret c210-1-credentials kubectl delete assetendpointprofile c210-4a826d41 kubectl delete asset c210-4a826d41-ptz -kubectl delete brokerlistener test-listener -n azure-iot-operations +kubectl delete brokerlistener aio-broker-listener-non-tls -n azure-iot-operations kubectl set env deployment/aio-opc-supervisor opcuabroker_MqttOptions__MqttBroker=mqtts://aio-broker.azure-iot-operations:18883 opcuabroker_MqttOptions__AuthenticationMethod=ServiceAccountToken -n azure-iot-operations ``` 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-GetTaskDebugInfo.ps1 b/samples/media-connector-invoke-test/Invoke-GetTaskDebugInfo.ps1 new file mode 100644 index 0000000..e1280ea --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-GetTaskDebugInfo.ps1 @@ -0,0 +1,22 @@ +<# + Get the task debug info +#> +param ( + [Parameter( + HelpMessage="AIO namespace.")] + [string]$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath .aio_namespace) -Raw), + [Parameter( + HelpMessage="Asset name.")] + [string]$assetName, + [Parameter( + HelpMessage="Datapoint name.")] + [string]$datapointName +) + +$mrpcTopic = "$aioNamespace/asset-operations/${assetName}/get-task-debug-info" + +$mrpcResponseTopic = "$mrpcTopic/response" + +$mrpcPayload = "{`"datapoint`":`"${datapointName}`"}" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-mRPC.ps1") -mrpcTopic $mrpcTopic -mrpcResponseTopic $mrpcResponseTopic -mrpcPayload $mrpcPayload diff --git a/samples/media-connector-invoke-test/Invoke-GetTaskErrorString.ps1 b/samples/media-connector-invoke-test/Invoke-GetTaskErrorString.ps1 new file mode 100644 index 0000000..e639a54 --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-GetTaskErrorString.ps1 @@ -0,0 +1,22 @@ +<# + Get the task error string +#> +param ( + [Parameter( + HelpMessage="AIO namespace.")] + [string]$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath .aio_namespace) -Raw), + [Parameter( + HelpMessage="Asset name.")] + [string]$assetName, + [Parameter( + HelpMessage="Datapoint name.")] + [string]$datapointName +) + +$mrpcTopic = "$aioNamespace/asset-operations/${assetName}/get-task-error-string" + +$mrpcResponseTopic = "$mrpcTopic/response" + +$mrpcPayload = "{`"datapoint`":`"${datapointName}`"}" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-mRPC.ps1") -mrpcTopic $mrpcTopic -mrpcResponseTopic $mrpcResponseTopic -mrpcPayload $mrpcPayload diff --git a/samples/media-connector-invoke-test/Invoke-GetTaskOutputString.ps1 b/samples/media-connector-invoke-test/Invoke-GetTaskOutputString.ps1 new file mode 100644 index 0000000..689027b --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-GetTaskOutputString.ps1 @@ -0,0 +1,22 @@ +<# + Get the task output string +#> +param ( + [Parameter( + HelpMessage="AIO namespace.")] + [string]$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath .aio_namespace) -Raw), + [Parameter( + HelpMessage="Asset name.")] + [string]$assetName, + [Parameter( + HelpMessage="Datapoint name.")] + [string]$datapointName +) + +$mrpcTopic = "$aioNamespace/asset-operations/${assetName}/get-task-output-string" + +$mrpcResponseTopic = "$mrpcTopic/response" + +$mrpcPayload = "{`"datapoint`":`"${datapointName}`"}" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-mRPC.ps1") -mrpcTopic $mrpcTopic -mrpcResponseTopic $mrpcResponseTopic -mrpcPayload $mrpcPayload diff --git a/samples/media-connector-invoke-test/Invoke-GetTaskState.ps1 b/samples/media-connector-invoke-test/Invoke-GetTaskState.ps1 new file mode 100644 index 0000000..769d02f --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-GetTaskState.ps1 @@ -0,0 +1,22 @@ +<# + Get the task state +#> +param ( + [Parameter( + HelpMessage="AIO namespace.")] + [string]$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath .aio_namespace) -Raw), + [Parameter( + HelpMessage="Asset name.")] + [string]$assetName, + [Parameter( + HelpMessage="Datapoint name.")] + [string]$datapointName +) + +$mrpcTopic = "$aioNamespace/asset-operations/${assetName}/get-task-state" + +$mrpcResponseTopic = "$mrpcTopic/response" + +$mrpcPayload = "{`"datapoint`":`"${datapointName}`"}" + +. (Join-Path -Path $PSScriptRoot -ChildPath "Invoke-mRPC.ps1") -mrpcTopic $mrpcTopic -mrpcResponseTopic $mrpcResponseTopic -mrpcPayload $mrpcPayload 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..9d50e93 --- /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 -Path $PSScriptRoot -ChildPath "Test-Prerequisites.ps1") | Out-Null + +$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".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 -Path $PSScriptRoot -ChildPath "Install-ResourceFile.ps1") -resourceFile "${aepName}.yaml" +. (Join-Path -Path $PSScriptRoot -ChildPath "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 -Path $PSScriptRoot -ChildPath "Uninstall-ResourceFile.ps1") -resourceFile "${assetName}.yaml" + . (Join-Path -Path $PSScriptRoot -ChildPath "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..ea3b16f --- /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-TestClipToMqttAutostart.ps1 b/samples/media-connector-invoke-test/Invoke-TestClipToMqttAutostart.ps1 new file mode 100644 index 0000000..6f9c0a7 --- /dev/null +++ b/samples/media-connector-invoke-test/Invoke-TestClipToMqttAutostart.ps1 @@ -0,0 +1,18 @@ +$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-mqtt-autostart" +Write-Host "Asset name: $assetName" + +$datapointName = "clip-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-TestSnapshotToFsAutostart.ps1 b/samples/media-connector-invoke-test/Invoke-TestSnapshotToFsAutostart.ps1 new file mode 100644 index 0000000..8e8ae2e --- /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..ce30961 --- /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..850beac --- /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/README.md b/samples/media-connector-invoke-test/README.md index 113becf..b494caf 100644 --- a/samples/media-connector-invoke-test/README.md +++ b/samples/media-connector-invoke-test/README.md @@ -1,8 +1,96 @@ -# 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's designed to be secure, scalable and fault-tolerant. It's responsible for the ingestion, storage, and distribution of media content; it also takes care of the management of media metadata and the generation of media thumbnails. + +To learn more, see [What is the Azure IoT Operations media connector?](https://learn.microsoft.com/azure/iot-operations/discover-manage-assets/overview-media-connector) + +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. + +## Prerequisites + +To install the prerequisites, use the following instructions: + +### Windows + +Run these commands from the command line: + +```cmd +winget install -e --id Microsoft.PowerShell +winget install -e --id Kubernetes.kubectl +winget install -e --id Microsoft.Azure.Kubelogin +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 + +Use the following links to install the required tools: + +- [PowerShell](https://learn.microsoft.com/powershell/scripting/install/install-ubuntu) +- [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-linux) +- [Helm](https://helm.sh/docs/intro/install/) +- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/) + +To install the **mosquitto** clients, run: + +```bash +sudo apt install mosquitto-clients +``` + +## Get started + +1. The scripts are designed to run on PowerShell 7 or newer. To test if you have the necessary prerequisites, run the `Test-Prerequisites.ps1` script. The demo files should be in a path without spaces. +1. [Deploy Azure IoT Operations](https://learn.microsoft.com/azure/iot-operations/deploy-iot-ops/overview-deploy). The Azure IoT Operations Kubernetes cluster should be configured as the `kubectl` current context. +1. To install the sample media server, use the files in the `media-server/` folder. +1. You should have a listener without TLS configured on port 1883. Use the files in the `broker-listener/` folder to deploy a suitable listener. +1. To verify the listener is accessible, run the `Update-AioMqEndpointFile.ps1` script. +1. Run the various test scripts, `Invoke-Test*.ps1`, to try out different 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 you can retrieve it. + + Each script deploys an asset endpoint and asset, and then monitors their activity. Use `Ctrl+C` to end the monitoring, remove the asset endpoint and asset, and terminate the script. + +## Changes since Azure IoT Operations M2 and M3 preview releases + +- Additional test scripts have been added to demonstrate the capabilities of the Azure IoT Operations media connector. +- Uses 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 connector for ONVIF that's currently in development. +- Limits to the number of concurrent connections and use of the file system 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. +- **media-connector-demo.mermaid and produced .png and .svg**: Diagram of the demo environment. +- **MQTT client container (mqtt-client)**: This folder contains PowerShell scripts and kubernetes resources that show how to deploy a container with an MQTT client configured for secure access. +- **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 endpoints that you can use to configure the media connector. +- **resources/asset-*.yaml**: Example assets that you can use 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 starts monitoring for file changes on the Azure IoT Operations media connector container. +- **Start-RtspStreamViewer.ps1**: This PowerShell script starts the default browser to look at the RTSP stream 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..838c5c7 --- /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 -Path $PSScriptRoot -ChildPath "Test-Prerequisites.ps1") + +$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".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-rtsp-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-InteractiveSession.ps1 b/samples/media-connector-invoke-test/Start-InteractiveSession.ps1 new file mode 100644 index 0000000..69ceb1c --- /dev/null +++ b/samples/media-connector-invoke-test/Start-InteractiveSession.ps1 @@ -0,0 +1,27 @@ +<# + Start an interactive session in the AIO Media Connector pod. +#> + +Write-Host (Split-Path -Path $PSCommandPath -Leaf).ToUpper() -ForegroundColor White + +. (Join-Path -Path $PSScriptRoot -ChildPath "Test-Prerequisites.ps1") + +$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$podName = (kubectl get pods -n $aioConnectorsNamespace -l app.kubernetes.io/component=aio-opc-rtsp-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 "Starting an interactive session..." + . kubectl exec --stdin --tty $podName -n $aioConnectorsNamespace -- /bin/bash +} finally { + Write-Host "`nThe interactive session 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..97f378c --- /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 -Path $PSScriptRoot -ChildPath "Test-Prerequisites.ps1") + +. (Join-Path -Path $PSScriptRoot -ChildPath "Update-AioMqEndpointFile.ps1") + +$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioMqHost = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_mq_host") -Raw).Trim() +Write-Host "AIO MQ host: $aioMqHost" + +$aioMqPort = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_mq_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..e3c0676 --- /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 -Path $PSScriptRoot -ChildPath "Test-Prerequisites.ps1") + +. (Join-Path -Path $PSScriptRoot -ChildPath "Update-MediaServerConfigFiles.ps1") + +$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_namespace") -Raw).Trim() +Write-Host "AIO namespace: $aioNamespace" + +$aioConnectorsNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_connectors_namespace") -Raw).Trim() +Write-Host "AIO connectors namespace: $aioConnectorsNamespace" + +$mediaServer = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath ".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..4b7dd57 --- /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 -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 "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-AioMqEndpointFile.ps1 b/samples/media-connector-invoke-test/Update-AioMqEndpointFile.ps1 new file mode 100644 index 0000000..f366c88 --- /dev/null +++ b/samples/media-connector-invoke-test/Update-AioMqEndpointFile.ps1 @@ -0,0 +1,54 @@ +#Requires -Version 7 +<# + Update the AIO MQ endpoint file. +#> + +$aioNamespace = (Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath .config_aio_namespace) -Raw).Trim() +Write-Host "AIO connectors namespace: ${aioNamespace}" + +$aioMqPort=1883 + +Function Detect-MQ { + Param ( + [string]$serviceName + ) + Write-Host "Detecting the MQ endpoint..." + $aioMqEndpointIp=(kubectl get service ${serviceName} ` + --namespace ${aioNamespace} ` + --output jsonpath='{.status.loadBalancer.ingress[0].ip}') + If (${aioMqEndpointIp}) { + Write-Host "AIO MQ endpoint IP: ${aioMqEndpointIp}" + $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 MQ endpoint hostname: ${aioMqEndpointHostname}" + $aioMqEndpoint="mqtt://${aioMqEndpointHostname}:${aioMqPort}" + $aioMqHost=$aioMqEndpointHostname + } + } +} + +. Detect-MQ -serviceName "aio-broker" +If (-not ${aioMqEndpointIp} -and -not ${aioMqEndpointHostname}) { + . Detect-MQ -serviceName "aio-broker-listener-non-tls" +} + +If (-not ${aioMqEndpointIp} -and -not ${aioMqEndpointHostname}) { + Throw "Failed to detect the AIO MQ endpoint." + Exit 1 +} + +Write-Host "AIO MQ endpoint: ${aioMqEndpoint}" +Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_mq_endpoint") -InputObject $aioMqEndpoint -NoNewline + +Write-Host "AIO MQ host: ${aioMqHost}" +Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_mq_host") -InputObject $aioMqHost -NoNewline + +Write-Host "AIO MQ port: ${aioMqPort}" +Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ".config_aio_mq_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..22083ef --- /dev/null +++ b/samples/media-connector-invoke-test/broker-listener/broker-listener.yaml @@ -0,0 +1,12 @@ +apiVersion: mqttbroker.iotoperations.azure.com/v1 +kind: BrokerListener +metadata: + name: aio-broker-listener-non-tls + namespace: azure-iot-operations +spec: + brokerRef: default + serviceType: LoadBalancer + serviceName: aio-broker-listener-non-tls + ports: + - port: 1883 + protocol: Mqtt \ No newline at end of file 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 0000000000000000000000000000000000000000..81f33c1337ff4d86b57451ba0462b0b76d1da396 GIT binary patch literal 124731 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
$p;HwHml>UH{YM^$9&H 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 ./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..4bb0362 --- /dev/null +++ b/samples/media-connector-invoke-test/media-server/README.md @@ -0,0 +1,15 @@ +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 +}