Skip to content

Commit ed99abd

Browse files
authored
Merge branch 'develop' into CO5/Develop
2 parents f2c8f03 + e5ea560 commit ed99abd

File tree

163 files changed

+15733
-15947
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

163 files changed

+15733
-15947
lines changed

.github/workflows/backend-publish-azure.yml

-1
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,3 @@ jobs:
6767
app-name: ${{ env.AZURE_WEBAPP_NAME }}
6868
publish-profile: ${{ secrets.AZURE_PROFILEDESIGNER_BACK_PUBLISHSETTINGS }}
6969
package: ${{ env.PROJECT_DIRECTORY }}${{ env.PUBLISH_FOLDER }}
70-

.github/workflows/backend-publish-stage-azure.yml

-1
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,3 @@ jobs:
7070
app-name: ${{ env.AZURE_WEBAPP_NAME }}
7171
publish-profile: ${{ secrets.AZURE_PROFILEDESIGNER_BACK_STAGE_PUBLISHSETTINGS }}
7272
package: ${{ env.PROJECT_DIRECTORY }}${{ env.PUBLISH_FOLDER }}
73-

.github/workflows/smoke-tests.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# This workflow will build and test a .NET 6 web API.
2+
# The tests will be a subset of tests which run quickly while still getting good code coverage.
3+
name: Smoke Test|API|Profile Designer
4+
on:
5+
#manually trigger deploy
6+
workflow_dispatch:
7+
# Trigger the workflow on push
8+
push:
9+
branches:
10+
- feature/smoke-tests
11+
- develop
12+
- main
13+
pull_request:
14+
branches:
15+
- develop
16+
- main
17+
18+
19+
jobs:
20+
#call a common workflow which checks out, builds, publishes, zips, deploys to AWS Elastic beanstalk
21+
call-workflow-publish-common-aws:
22+
uses: ./.github/workflows/tests-shared.yml
23+
with:
24+
TEST_FILTER: 'SmokeTest="true"'
25+
BUILD_TARGET: 'Staging'
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Add to main branch to allow to be seen in other branches.
2+
# CESMII Profile Designer - Setup and test Profile Designer Web Page using Selenium Tests
3+
#
4+
# For more samples to get started with GitHub Action workflows to deploy to Azure, refer to https://github.com/Azure/actions-workflow-samples
5+
name: Test|In Browser|Profile Designer
6+
on:
7+
#manually trigger deploy
8+
workflow_dispatch:
9+
# Trigger the workflow on push
10+
#push:
11+
# branches:
12+
# - develop
13+
# - main
14+
#pull_request:
15+
# branches:
16+
# - develop
17+
# - main

.github/workflows/tests-shared.yml

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# This workflow will build and test a .NET 6 web API.
2+
# The tests will be a subset of tests which run quickly while still getting good code coverage.
3+
name: Shared | Tests | Common Test Workflow
4+
on:
5+
workflow_call:
6+
inputs:
7+
#ie Staging, Release
8+
BUILD_TARGET:
9+
required: true
10+
type: string
11+
#optional test filter (ie. filter on smoke test trait)
12+
TEST_FILTER:
13+
required: true
14+
type: string
15+
#'--filter SmokeTest="true"'
16+
17+
env:
18+
# set this to the path to your solution file, defaults to the repository root (this is the folder in the git repo)
19+
SOLUTION_DIRECTORY: './'
20+
# set this to the path to your web app project, defaults to the repository root (this is the folder in the git repo)
21+
PROJECT_DIRECTORY: './api/CESMII.ProfileDesigner.Api'
22+
# Solution file to use
23+
SOLUTION_FILE: 'CESMII.ProfileDesigner.sln'
24+
# Project file to use
25+
PROJECT_NAME: 'CESMII.ProfileDesigner.Api'
26+
# set this to the .NET core version to use
27+
NETCORE_VERSION: "6.0.x"
28+
29+
jobs:
30+
build:
31+
name: Build and Test .NET6 Web API
32+
runs-on: ubuntu-latest
33+
steps:
34+
#dynamically set up env variables based on inputs
35+
- name: Dynamically set test filter based on input filter
36+
run: |
37+
if [ ${{inputs.TEST_FILTER}} != "" ]; then
38+
echo "Test uses filter..."
39+
echo "TEST_LABEL=Filter=${{inputs.TEST_FILTER}}" >> $GITHUB_ENV
40+
echo "TEST_FILTER=--filter ${{inputs.TEST_FILTER}}" >> $GITHUB_ENV
41+
else
42+
echo "Test does not use filter..."
43+
echo "TEST_LABEL=" >> $GITHUB_ENV
44+
echo "TEST_FILTER=" >> $GITHUB_ENV
45+
fi
46+
47+
- uses: actions/checkout@v2
48+
with:
49+
submodules: true
50+
- name: Set up dotnet Core ${{ env.NETCORE_VERSION }}
51+
uses: actions/setup-dotnet@v1
52+
with:
53+
dotnet-version: ${{ env.NETCORE_VERSION }}
54+
55+
- name: Start PostgreSQL on Ubuntu for use by integration tests
56+
run: |
57+
sudo systemctl start postgresql.service
58+
pg_isready
59+
- name: Create additional user
60+
run: |
61+
sudo -u postgres psql --command="CREATE USER profiledesigner SUPERUSER PASSWORD 'cesmii'" --command="\du"
62+
- name: List existing databases
63+
run: |
64+
sudo -u postgres psql -l
65+
- name: Create database
66+
run: |
67+
sudo -u postgres psql --command="CREATE DATABASE profile_designer_local_test WITH OWNER = profiledesigner TABLESPACE = pg_default CONNECTION LIMIT = -1;"
68+
- name: Create schema
69+
run: |
70+
ls -l ./sql
71+
head -5 ./sql/CESMII.ProfileDesigner.DB.sql
72+
sudo -u postgres psql -d profile_designer_local_test < ./sql/CESMII.ProfileDesigner.DB.sql
73+
#sudo -u postgres psql -d profile_designer_local_test --file ./sql/CESMII.ProfileDesigner.DB.sql
74+
- name: List existing databases
75+
run: |
76+
sudo -u postgres psql -l
77+
78+
- name: Restore dependencies (${{env.SOLUTION_FILE}})
79+
run: dotnet restore ${{env.SOLUTION_FILE}}
80+
working-directory: ${{env.SOLUTION_DIRECTORY}}
81+
- name: Build (${{env.SOLUTION_FILE}})
82+
run: dotnet build ${{env.SOLUTION_FILE}} --configuration ${{inputs.BUILD_TARGET}} --no-restore
83+
working-directory: ${{env.SOLUTION_DIRECTORY}}
84+
85+
- name: Test (${{env.SOLUTION_FILE}}) ${{env.TEST_LABEL}}
86+
run: dotnet test ${{env.SOLUTION_FILE}} ${{env.TEST_FILTER}} --configuration ${{ inputs.BUILD_TARGET }} --no-build --verbosity normal -l:"console;verbosity=normal"
87+
working-directory: ${{env.SOLUTION_DIRECTORY}}

api/CESMII.OpcUa.CloudLibraryResolver.DependencyInjection/CESMII.OpcUa.CloudLibraryResolver.DependencyInjection.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
2626
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
2727
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" />
28-
<PackageReference Include="CESMII.OpcUa.NodeSetImporter" Version="1.0.13" />
28+
<PackageReference Include="CESMII.OpcUa.NodeSetImporter" Version="1.0.16" />
2929
</ItemGroup>
3030

3131
<ItemGroup>

api/CESMII.OpcUa.CloudLibraryResolver.DependencyInjection/UANodeSetCloudLibraryResolverExtensions.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ public static class UANodeSetCloudLibraryResolverExtensions
1717
public static IServiceCollection AddCloudLibraryResolver(this IServiceCollection services)
1818
{
1919
services
20-
.AddScoped<IUANodeSetResolverWithProgress, UANodeSetCloudLibraryResolver>(sp => new UANodeSetCloudLibraryResolver(sp.GetRequiredService<IOptions<UACloudLibClient.Options>>().Value))
20+
.AddScoped<IUANodeSetResolverWithPending, UANodeSetCloudLibraryResolver>(sp => new UANodeSetCloudLibraryResolver(sp.GetRequiredService<IOptions<UACloudLibClient.Options>>().Value))
2121
;
2222
return services;
2323
}
2424
public static IServiceCollection AddCloudLibraryResolver(this IServiceCollection services, IConfiguration configurationSection)
2525
{
2626
services
2727
.Configure<UACloudLibClient.Options>(configurationSection)
28-
.AddScoped<IUANodeSetResolverWithProgress, UANodeSetCloudLibraryResolver>(sp => new UANodeSetCloudLibraryResolver(sp.GetRequiredService<IOptions<UACloudLibClient.Options>>().Value))
28+
.AddScoped<IUANodeSetResolverWithPending, UANodeSetCloudLibraryResolver>(sp => new UANodeSetCloudLibraryResolver(sp.GetRequiredService<IOptions<UACloudLibClient.Options>>().Value))
2929
;
3030
return services;
3131
}

api/CESMII.OpcUa.CloudLibraryResolver/CESMII.OpcUa.CloudLibraryResolver.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
</ItemGroup>
2727

2828
<ItemGroup>
29-
<PackageReference Include="CESMII.OpcUa.NodeSetImporter" Version="1.0.13" />
29+
<PackageReference Include="CESMII.OpcUa.NodeSetImporter" Version="1.0.16" />
3030
<ProjectReference Include="..\..\common\Opc.Ua.Cloud.Library.Client\Opc.Ua.Cloud.Library.Client.csproj" />
3131
</ItemGroup>
3232

api/CESMII.OpcUa.CloudLibraryResolver/CloudLibraryResolver.cs

+24-2
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
namespace CESMII.OpcUa.NodeSetImporter
1616
{
17-
public class UANodeSetCloudLibraryResolver : IUANodeSetResolverWithProgress
17+
public class UANodeSetCloudLibraryResolver : IUANodeSetResolverWithPending
1818
{
1919
public OnResolveNodeSets OnResolveNodeSets { get; set; }
2020
public OnNodeSet OnDownloadNodeSet { get; set; }
2121
public OnNodeSet OnNodeSetFound { get; set; }
2222
public OnNodeSet OnNodeSetNotFound { get; set; }
2323

24+
public Func<Nodeset, bool> FilterPendingNodeSet { get; set; }
25+
2426
public UANodeSetCloudLibraryResolver(string strUserName, string strPassword)
2527
{
2628
_client = new UACloudLibClient(strUserName, strPassword);
@@ -62,9 +64,29 @@ public async Task<IEnumerable<String>> ResolveNodeSetsAsync(List<ModelNameAndVer
6264
{
6365
nodesetWithURIAndDate.Add((nodeSet.NamespaceUri.OriginalString, nodeSet.PublicationDate, nodeSet.Identifier.ToString(CultureInfo.InvariantCulture), nodeSet.NodesetXml));
6466
}
67+
try
68+
{
69+
if (FilterPendingNodeSet != null)
70+
{
71+
var pendingNodeSets = await _client.GetNodeSetsPendingApprovalAsync(namespaceUri: missingModel.ModelUri).ConfigureAwait(false);
72+
var filteredPending = pendingNodeSets.Nodes.Where(FilterPendingNodeSet).ToList();
73+
foreach(var pending in filteredPending)
74+
{
75+
var pendingNodeSetDownload = await _client.GetNodeSetDependencies(identifier: pending.Identifier.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
76+
foreach (var nodeSet in pendingNodeSetDownload)
77+
{
78+
nodesetWithURIAndDate.Add((nodeSet.NamespaceUri.OriginalString, nodeSet.PublicationDate, nodeSet.Identifier.ToString(CultureInfo.InvariantCulture), nodeSet.NodesetXml));
79+
}
80+
}
81+
}
82+
}
83+
catch (Exception ex)
84+
{
85+
86+
}
6587
}
6688
}
67-
catch (Exception) // TODO more specific exception to detect if cloudlib doesn't support GetNodeSetDependencies
89+
catch (GraphQlNotSupportedException)
6890
{
6991
// Fall back to retrieving and downloading all matching namespaces
7092
var namespacesAndIds = await _client.GetNamespaceIdsAsync().ConfigureAwait(false);

api/CESMII.OpcUa.CloudLibraryResolver/IUANodeSetResolverWithProgress.cs

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2022
66
*/
77

8+
using Opc.Ua.Cloud.Library.Client;
89
using System;
910

1011
namespace CESMII.OpcUa.NodeSetImporter
@@ -15,8 +16,13 @@ public interface IUANodeSetResolverWithProgress : IUANodeSetResolver
1516
public OnNodeSet OnDownloadNodeSet { get; set; }
1617
public OnNodeSet OnNodeSetFound { get; set; }
1718
public OnNodeSet OnNodeSetNotFound { get; set; }
19+
1820
}
1921
public delegate void OnResolveNodeSets();
2022
public delegate void OnNodeSet(string namespaceUri, DateTime? publicationDate);
2123

24+
public interface IUANodeSetResolverWithPending : IUANodeSetResolverWithProgress
25+
{
26+
public Func<Nodeset, bool> FilterPendingNodeSet { get; set; }
27+
}
2228
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Usage
2+
3+
## Basic
4+
5+
Pass resolver to UANodeSetCacheManager constructor:
6+
```c#
7+
var cacheManager = new UANodeSetCacheManager(myNodeSetCache, _cloudLibResolver);
8+
```
9+
## With progress
10+
```c#
11+
try
12+
{
13+
_cloudLibResolver.OnDownloadNodeSet += callback;
14+
var cacheManager = new UANodeSetCacheManager(myNodeSetCache, _cloudLibResolver);
15+
resultSet = cacheManager.ImportNodeSets(nodeSetXmlStringList, false, userToken);
16+
}
17+
finally
18+
{
19+
_cloudLibResolver.OnDownloadNodeSet -= callback;
20+
}
21+
```
22+
23+
## With nodesets pending approval
24+
25+
```c#
26+
try
27+
{
28+
_cloudLibResolver.OnDownloadNodeSet += callback;
29+
_cloudLibResolver.FilterPendingNodeSet = (n => true); // All pending nodesets
30+
var cacheManager = new UANodeSetCacheManager(myNodeSetCache, _cloudLibResolver);
31+
resultSet = cacheManager.ImportNodeSets(nodeSetXmlStringList, false, userToken);
32+
}
33+
finally
34+
{
35+
_cloudLibResolver.OnDownloadNodeSet -= callback;
36+
}
37+
```
38+
39+
### Filter by user id
40+
```c#
41+
_cloudLibResolver.FilterPendingNodeSet = (n =>
42+
{
43+
return n.Metadata.UserId == userId;
44+
}
45+
);
46+
```
47+
48+
### Filter by user id for the CESMII cloud library when used via CESMII Profile Designer
49+
```c#
50+
_cloudLibResolver.FilterPendingNodeSet = (n =>
51+
{
52+
return n.Metadata.UserId == userId
53+
|| (n.Metadata?.AdditionalProperties?
54+
.Any(p => p.Name == ICloudLibDal<CloudLibProfileModel>.strCESMIIUserInfo
55+
&& p.Value.StartsWith($"{userId,}")) ?? false);
56+
}
57+
);
58+
```
59+
60+
61+
## Dependency Injection
62+
Add service in startup.cs / program.cs:
63+
```c#
64+
services.AddCloudLibraryResolver();
65+
```
66+
67+
Provide configuration:
68+
```json
69+
"CloudLibrary": {
70+
"UserName": "something",
71+
"Password": "secure",
72+
"EndPoint": "https://localhost:5007"
73+
}
74+
```
75+
76+
Request as IUANodeSetResolverWithPending:
77+
```c#
78+
services.GetService<IUANodeSetResolverWithPending>();
79+
```
80+

api/CESMII.ProfileDesigner.Api.Shared/CESMII.ProfileDesigner.Api.Shared.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
<ItemGroup>
99
<FrameworkReference Include="Microsoft.AspNetCore.App" />
10-
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.11.1" />
11-
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.11.1" />
10+
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.35.0" />
11+
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.35.0" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

0 commit comments

Comments
 (0)