Skip to content

Commit 16f8496

Browse files
authored
(#244) Added infra for Mongo Community and Mongo-Cosmos (#257)
* (#244) Added Cosmos MongoDB infrastructure files * (#244) Added 2 MongoDB instances (Community and Cosmos) and centralized connection strings.
1 parent 128aef0 commit 16f8496

17 files changed

+344
-46
lines changed

infra/main.bicep

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ module resources './resources.bicep' = {
5050

5151
output AZSQL_CONNECTION_STRING string = resources.outputs.AZSQL_CONNECTIONSTRING
5252
output COSMOS_CONNECTION_STRING string = resources.outputs.COSMOS_CONNECTIONSTRING
53+
output MONGO_CONNECTION_STRING string = resources.outputs.MONGO_CONNECTIONSTRING
54+
output MONGOACI_CONNECTION_STRING string = resources.outputs.MONGOACI_CONNECTIONSTRING
5355
output MYSQL_CONNECTION_STRING string = resources.outputs.MYSQL_CONNECTIONSTRING
5456
output PGSQL_CONNECTION_STRING string = resources.outputs.PGSQL_CONNECTIONSTRING
5557
output SERVICE_ENDPOINT string = resources.outputs.SERVICE_ENDPOINT

infra/modules/aci-mongodb.bicep

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
targetScope = 'resourceGroup'
2+
3+
@secure()
4+
@description('The password for the administrator')
5+
param administratorPassword string
6+
7+
@description('The username for the administrator')
8+
param administratorUsername string = 'tester'
9+
10+
@description('The image URI to use.')
11+
param image string = 'mongo'
12+
13+
@minLength(1)
14+
@description('Primary location for all resources')
15+
param location string = resourceGroup().location
16+
17+
@description('The port # to expose in the Docker image')
18+
param port int = 27017
19+
20+
@description('The name of the Mongo Server to create.')
21+
param serverName string
22+
23+
@description('The list of tags to apply to all resources.')
24+
param tags object = {}
25+
26+
/*********************************************************************************/
27+
28+
resource containerGroup 'Microsoft.ContainerInstance/containerGroups@2023-05-01' = {
29+
name: toLower(serverName)
30+
location: location
31+
tags: tags
32+
properties: {
33+
containers: [
34+
{
35+
name: toLower(serverName)
36+
properties: {
37+
image: image
38+
environmentVariables: [
39+
{ name: 'MONGO_INITDB_ROOT_USERNAME', value: administratorUsername }
40+
{ name: 'MONGO_INITDB_ROOT_PASSWORD', secureValue: administratorPassword }
41+
]
42+
ports: [
43+
{
44+
port: port
45+
protocol: 'TCP'
46+
}
47+
]
48+
resources: {
49+
requests: {
50+
cpu: 2
51+
memoryInGB: 2
52+
}
53+
}
54+
}
55+
}
56+
]
57+
osType: 'Linux'
58+
restartPolicy: 'Always'
59+
ipAddress: {
60+
type: 'Public'
61+
ports: [
62+
{
63+
port: port
64+
protocol: 'TCP'
65+
}
66+
]
67+
}
68+
}
69+
}
70+
71+
/*********************************************************************************/
72+
73+
#disable-next-line outputs-should-not-contain-secrets
74+
output MONGO_CONNECTIONSTRING string = 'mongodb://${administratorUsername}:${administratorPassword}@${containerGroup.properties.ipAddress.ip}:27017/'

infra/modules/cosmos-mongodb.bicep

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
targetScope = 'resourceGroup'
2+
3+
@minLength(1)
4+
@description('The name of the test container to create')
5+
param containerName string = 'Movies'
6+
7+
@minLength(1)
8+
@description('The name of the test database to create')
9+
param databaseName string = 'unittests'
10+
11+
@minLength(1)
12+
@description('Primary location for all resources')
13+
param location string = resourceGroup().location
14+
15+
@allowed(['3.2', '3.6', '4.0', '4.2'])
16+
@description('Specifies the MongoDB server version to use.')
17+
param mongoVersion string = '4.2'
18+
19+
@description('The name of the Mongo Server to create.')
20+
param serverName string
21+
22+
@description('The list of tags to apply to all resources.')
23+
param tags object = {}
24+
25+
/*********************************************************************************/
26+
27+
var compositeIndices = [
28+
[
29+
{ path: '/BestPictureWinner', order: 'ascending' }
30+
{ path: '/id', order: 'ascending' }
31+
]
32+
[
33+
{ path: '/BestPictureWinner', order: 'descending' }
34+
{ path: '/id', order: 'ascending' }
35+
]
36+
[
37+
{ path: '/Duration', order: 'ascending' }
38+
{ path: '/id', order: 'ascending' }
39+
]
40+
[
41+
{ path: '/Duration', order: 'descending' }
42+
{ path: '/id', order: 'ascending' }
43+
]
44+
[
45+
{ path: '/Rating', order: 'ascending' }
46+
{ path: '/id', order: 'ascending' }
47+
]
48+
[
49+
{ path: '/Rating', order: 'descending' }
50+
{ path: '/id', order: 'ascending' }
51+
]
52+
[
53+
{ path: '/ReleaseDate', order: 'ascending' }
54+
{ path: '/id', order: 'ascending' }
55+
]
56+
[
57+
{ path: '/ReleaseDate', order: 'descending' }
58+
{ path: '/id', order: 'ascending' }
59+
]
60+
[
61+
{ path: '/Title', order: 'ascending' }
62+
{ path: '/id', order: 'ascending' }
63+
]
64+
[
65+
{ path: '/Title', order: 'descending' }
66+
{ path: '/id', order: 'ascending' }
67+
]
68+
[
69+
{ path: '/UpdatedAt', order: 'ascending' }
70+
{ path: '/id', order: 'ascending' }
71+
]
72+
[
73+
{ path: '/UpdatedAt', order: 'descending' }
74+
{ path: '/id', order: 'ascending' }
75+
]
76+
[
77+
{ path: '/Year', order: 'ascending' }
78+
{ path: '/id', order: 'ascending' }
79+
]
80+
[
81+
{ path: '/Year', order: 'descending' }
82+
{ path: '/id', order: 'ascending' }
83+
]
84+
[
85+
{ path: '/Year', order: 'ascending' }
86+
{ path: '/Title', order: 'ascending' }
87+
{ path: '/id', order: 'ascending' }
88+
]
89+
[
90+
{ path: '/Year', order: 'descending' }
91+
{ path: '/Title', order: 'ascending' }
92+
{ path: '/id', order: 'ascending' }
93+
]
94+
[
95+
{ path: '/Year', order: 'ascending' }
96+
{ path: '/Title', order: 'descending' }
97+
{ path: '/id', order: 'ascending' }
98+
]
99+
[
100+
{ path: '/Year', order: 'descending' }
101+
{ path: '/Title', order: 'descending' }
102+
{ path: '/id', order: 'ascending' }
103+
]
104+
]
105+
106+
/*********************************************************************************/
107+
108+
resource account 'Microsoft.DocumentDB/databaseAccounts@2022-05-15' = {
109+
name: toLower(serverName)
110+
location: location
111+
kind: 'MongoDB'
112+
tags: tags
113+
properties: {
114+
apiProperties: {
115+
serverVersion: mongoVersion
116+
}
117+
capabilities: [
118+
{
119+
name: 'DisableRateLimitingResponses'
120+
}
121+
]
122+
consistencyPolicy: {
123+
defaultConsistencyLevel: 'Session'
124+
}
125+
databaseAccountOfferType: 'Standard'
126+
disableLocalAuth: false
127+
locations: [
128+
{
129+
locationName: location
130+
isZoneRedundant: false
131+
}
132+
]
133+
}
134+
}
135+
136+
resource database 'Microsoft.DocumentDB/databaseAccounts/mongodbDatabases@2022-05-15' = {
137+
parent: account
138+
name: databaseName
139+
tags: tags
140+
properties: {
141+
resource: {
142+
id: databaseName
143+
}
144+
options: {
145+
throughput: 400
146+
}
147+
}
148+
}
149+
150+
resource collection 'Microsoft.DocumentDb/databaseAccounts/mongodbDatabases/collections@2022-05-15' = {
151+
parent: database
152+
name: containerName
153+
tags: tags
154+
properties: {
155+
resource: {
156+
id: containerName
157+
shardKey: {
158+
_id: 'Hash'
159+
}
160+
indexes: [
161+
{
162+
key: {
163+
keys: [
164+
'_id'
165+
]
166+
}
167+
}
168+
{
169+
key: {
170+
keys: [
171+
'$**'
172+
]
173+
}
174+
}
175+
]
176+
}
177+
}
178+
}
179+
/*********************************************************************************/
180+
181+
#disable-next-line outputs-should-not-contain-secrets
182+
output MONGODB_CONNECTIONSTRING string = account.listConnectionStrings().connectionStrings[1].connectionString

infra/resources.bicep

+26
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ var azsqlServerName = 'sql-${resourceToken}'
3535
var cosmosServerName = 'cosmos-${resourceToken}'
3636
var pgsqlServerName = 'pgsql-${resourceToken}'
3737
var mysqlServerName = 'mysql-${resourceToken}'
38+
var mongoServerName = 'mongo-${resourceToken}'
39+
var mongoaciServerName = 'mongoaci-${resourceToken}'
3840

3941
var testDatabaseName = 'unittests'
4042
var cosmosContainerName = 'Movies'
@@ -103,6 +105,28 @@ module cosmos './modules/cosmos.bicep' = {
103105
}
104106
}
105107

108+
module mongodb './modules/cosmos-mongodb.bicep' = {
109+
name: 'mongo-deployment-${resourceToken}'
110+
params: {
111+
location: location
112+
tags: tags
113+
databaseName: testDatabaseName
114+
containerName: cosmosContainerName
115+
serverName: mongoServerName
116+
}
117+
}
118+
119+
module mongoaci './modules/aci-mongodb.bicep' = {
120+
name: 'mongoaci-deployment-${resourceToken}'
121+
params: {
122+
location: location
123+
tags: tags
124+
serverName: mongoaciServerName
125+
administratorPassword: sqlAdminPassword
126+
127+
}
128+
}
129+
106130
module app_service './modules/appservice.bicep' = {
107131
name: 'appsvc-deployment-${resourceToken}'
108132
params: {
@@ -124,6 +148,8 @@ module app_service './modules/appservice.bicep' = {
124148

125149
output AZSQL_CONNECTIONSTRING string = azuresql.outputs.AZSQL_CONNECTIONSTRING
126150
output COSMOS_CONNECTIONSTRING string = cosmos.outputs.COSMOS_CONNECTIONSTRING
151+
output MONGO_CONNECTIONSTRING string = mongodb.outputs.MONGODB_CONNECTIONSTRING
152+
output MONGOACI_CONNECTIONSTRING string = mongoaci.outputs.MONGO_CONNECTIONSTRING
127153
output MYSQL_CONNECTIONSTRING string = mysql.outputs.MYSQL_CONNECTIONSTRING
128154
output PGSQL_CONNECTIONSTRING string = pgsql.outputs.PGSQL_CONNECTIONSTRING
129155
output SERVICE_ENDPOINT string = app_service.outputs.SERVICE_ENDPOINT

infra/scripts/write-runsettings.ps1

+13-7
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,26 @@
66
$outputs = (azd env get-values --output json | ConvertFrom-Json)
77
$outputFile = "tests\.runsettings"
88

9-
$fileContents = @"
9+
$prefix = @"
1010
<?xml version="1.0" encoding="utf-8"?>
1111
<RunSettings>
1212
<RunConfiguration>
1313
<EnvironmentVariables>
14-
<DATASYNC_AZSQL_CONNECTIONSTRING>$($outputs.AZSQL_CONNECTION_STRING)</DATASYNC_AZSQL_CONNECTIONSTRING>
15-
<DATASYNC_COSMOS_CONNECTIONSTRING>$($outputs.COSMOS_CONNECTION_STRING)</DATASYNC_COSMOS_CONNECTIONSTRING>
16-
<DATASYNC_MYSQL_CONNECTIONSTRING>$($outputs.MYSQL_CONNECTION_STRING)</DATASYNC_MYSQL_CONNECTIONSTRING>
17-
<DATASYNC_PGSQL_CONNECTIONSTRING>$($outputs.PGSQL_CONNECTION_STRING)</DATASYNC_PGSQL_CONNECTIONSTRING>
18-
<DATASYNC_SERVICE_ENDPOINT>$($outputs.SERVICE_ENDPOINT)</DATASYNC_SERVICE_ENDPOINT>
14+
15+
"@
16+
17+
$postfix = @"
1918
<ENABLE_SQL_LOGGING>true</ENABLE_SQL_LOGGING>
2019
</EnvironmentVariables>
2120
</RunConfiguration>
2221
</RunSettings>
2322
"@
2423

25-
$fileContents | Out-File -FilePath $outputFile
24+
$sb = New-Object System.Text.StringBuilder
25+
$outputs | Get-Member -MemberType Properties | Foreach-Object {
26+
$propertyName = $_.Name
27+
$propertyValue = [System.Security.SecurityElement]::Escape($outputs.$propertyName)
28+
$sb.AppendLine(" <$($propertyName)>$($propertyValue)</$($propertyName)>") | Out-Null
29+
}
30+
31+
$prefix + $sb.ToString() + $postfix | Out-File -FilePath $outputFile

tests/CommunityToolkit.Datasync.Client.Test/Live/SampleServerTests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using CommunityToolkit.Datasync.TestCommon.Databases;
56
using System.Net;
67
using System.Net.Http.Json;
78

@@ -10,8 +11,8 @@ namespace CommunityToolkit.Datasync.Client.Test.Live;
1011
[ExcludeFromCodeCoverage]
1112
public class SampleServerTests
1213
{
13-
private readonly bool liveTestsAreEnabled = Environment.GetEnvironmentVariable("DATASYNC_SERVICE_ENDPOINT") is not null;
14-
private readonly string serviceEndpoint = Environment.GetEnvironmentVariable("DATASYNC_SERVICE_ENDPOINT");
14+
private readonly bool liveTestsAreEnabled = ConnectionStrings.Service is not null;
15+
private readonly string serviceEndpoint = ConnectionStrings.Service;
1516

1617
[SkippableFact]
1718
public async Task Metadata_GetsSetByServer()

tests/CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test/AzureSqlEntityTableRepository_Tests.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@ public class AzureSqlEntityTableRepository_Tests(DatabaseFixture fixture, ITestO
1717
{
1818
#region Setup
1919
private readonly Random random = new();
20-
private readonly string connectionString = Environment.GetEnvironmentVariable("DATASYNC_AZSQL_CONNECTIONSTRING");
2120
private List<AzureSqlEntityMovie> movies = [];
2221

2322
public async Task InitializeAsync()
2423
{
25-
if (!string.IsNullOrEmpty(this.connectionString))
24+
if (!string.IsNullOrEmpty(ConnectionStrings.AzureSql))
2625
{
27-
Context = await AzureSqlDbContext.CreateContextAsync(this.connectionString, output);
26+
Context = await AzureSqlDbContext.CreateContextAsync(ConnectionStrings.AzureSql, output);
2827
this.movies = await Context.Movies.AsNoTracking().ToListAsync();
2928
}
3029
}
@@ -39,7 +38,7 @@ public async Task DisposeAsync()
3938

4039
private AzureSqlDbContext Context { get; set; }
4140

42-
protected override bool CanRunLiveTests() => !string.IsNullOrEmpty(this.connectionString);
41+
protected override bool CanRunLiveTests() => !string.IsNullOrEmpty(ConnectionStrings.AzureSql);
4342

4443
protected override async Task<AzureSqlEntityMovie> GetEntityAsync(string id)
4544
=> await Context.Movies.AsNoTracking().SingleOrDefaultAsync(m => m.Id == id);

0 commit comments

Comments
 (0)