Skip to content

Commit 8051114

Browse files
committed
Add Azure Storage check in Catalog health checks.
1 parent eb7abbc commit 8051114

8 files changed

Lines changed: 351 additions & 61 deletions

File tree

.env

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@
55
# The IP below should be swapped to your real IP or DNS name, like 192.168.88.248, etc. if testing from remote browsers or mobile devices
66

77
ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost
8-
ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92
8+
ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92
9+
ESHOP_AZURE_STORAGE_ACCOUNT=https://eshopstorageaccount.blob.core.windows.net/pics/
10+
ESHOP_AZURE_STORAGE_ACCOUNT_NAME=eshopstorageaccount
11+
ESHOP_AZURE_STORAGE_ACCOUNT_KEY=nugfkxI5hEajLIHARRnMkiO68UQK64MjaYssVkhTay4BvFjSTkJdVotbqU6aPtp2hcXa+ZfhBGKTCXMUDm5X4w==

docker-compose.override.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ services:
2929
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
3030
- PicBaseUrl=${ESHOP_AZURE_STORAGE_ACCOUNT:-http://localhost:5101/api/v1/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
3131
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
32+
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_ACCOUNT_NAME}
33+
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_ACCOUNT_KEY}
3234
- UseCustomizationData=True
3335
ports:
3436
- "5101:80"

eShopOnContainers-ServicesAndWebApps.sln

Lines changed: 108 additions & 57 deletions
Large diffs are not rendered by default.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Microsoft.WindowsAzure.Storage;
6+
using Microsoft.WindowsAzure.Storage.Auth;
7+
8+
namespace Microsoft.Extensions.HealthChecks
9+
{
10+
// REVIEW: Do we want these to continue to use default parameters?
11+
// REVIEW: What are the appropriate guards for these functions?
12+
13+
public static class AzureHealthCheckBuilderExtensions
14+
{
15+
public static HealthCheckBuilder AddAzureBlobStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string containerName = null, TimeSpan? cacheDuration = null)
16+
{
17+
var credentials = new StorageCredentials(accountName, accountKey);
18+
var storageAccount = new CloudStorageAccount(credentials, true);
19+
return AddAzureBlobStorageCheck(builder, storageAccount, containerName, cacheDuration);
20+
}
21+
22+
public static HealthCheckBuilder AddAzureBlobStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string containerName = null, TimeSpan? cacheDuration = null)
23+
{
24+
builder.AddCheck($"AzureBlobStorageCheck {storageAccount.BlobStorageUri} {containerName}", async () =>
25+
{
26+
bool result;
27+
try
28+
{
29+
var blobClient = storageAccount.CreateCloudBlobClient();
30+
31+
var properties = await blobClient.GetServicePropertiesAsync().ConfigureAwait(false);
32+
33+
if (!String.IsNullOrWhiteSpace(containerName))
34+
{
35+
var container = blobClient.GetContainerReference(containerName);
36+
37+
result = await container.ExistsAsync();
38+
}
39+
40+
result = true;
41+
}
42+
catch (Exception)
43+
{
44+
result = false;
45+
}
46+
47+
return result
48+
? HealthCheckResult.Healthy($"AzureBlobStorage {storageAccount.BlobStorageUri} is available")
49+
: HealthCheckResult.Unhealthy($"AzureBlobStorage {storageAccount.BlobStorageUri} is unavailable");
50+
}, cacheDuration ?? builder.DefaultCacheDuration);
51+
52+
return builder;
53+
}
54+
55+
public static HealthCheckBuilder AddAzureTableStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string tableName = null, TimeSpan? cacheDuration = null)
56+
{
57+
var credentials = new StorageCredentials(accountName, accountKey);
58+
var storageAccount = new CloudStorageAccount(credentials, true);
59+
return AddAzureTableStorageCheck(builder, storageAccount, tableName, cacheDuration);
60+
}
61+
62+
public static HealthCheckBuilder AddAzureTableStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string tableName = null, TimeSpan? cacheDuration = null)
63+
{
64+
builder.AddCheck($"AzureTableStorageCheck {storageAccount.TableStorageUri} {tableName}", async () =>
65+
{
66+
bool result;
67+
try
68+
{
69+
var tableClient = storageAccount.CreateCloudTableClient();
70+
71+
var properties = await tableClient.GetServicePropertiesAsync().ConfigureAwait(false);
72+
73+
if (String.IsNullOrWhiteSpace(tableName))
74+
{
75+
var table = tableClient.GetTableReference(tableName);
76+
77+
result = await table.ExistsAsync();
78+
}
79+
result = true;
80+
}
81+
catch (Exception)
82+
{
83+
result = false;
84+
}
85+
86+
return result
87+
? HealthCheckResult.Healthy($"AzureTableStorage {storageAccount.BlobStorageUri} is available")
88+
: HealthCheckResult.Unhealthy($"AzureTableStorage {storageAccount.BlobStorageUri} is unavailable");
89+
90+
}, cacheDuration ?? builder.DefaultCacheDuration);
91+
92+
return builder;
93+
}
94+
95+
public static HealthCheckBuilder AddAzureFileStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string shareName = null, TimeSpan? cacheDuration = null)
96+
{
97+
var credentials = new StorageCredentials(accountName, accountKey);
98+
var storageAccount = new CloudStorageAccount(credentials, true);
99+
return AddAzureFileStorageCheck(builder, storageAccount, shareName, cacheDuration);
100+
}
101+
102+
public static HealthCheckBuilder AddAzureFileStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string shareName = null, TimeSpan? cacheDuration = null)
103+
{
104+
builder.AddCheck($"AzureFileStorageCheck {storageAccount.FileStorageUri} {shareName}", async () =>
105+
{
106+
bool result;
107+
try
108+
{
109+
var fileClient = storageAccount.CreateCloudFileClient();
110+
111+
var properties = await fileClient.GetServicePropertiesAsync().ConfigureAwait(false);
112+
113+
if (!String.IsNullOrWhiteSpace(shareName))
114+
{
115+
var share = fileClient.GetShareReference(shareName);
116+
117+
result = await share.ExistsAsync();
118+
}
119+
120+
result = true;
121+
}
122+
catch (Exception)
123+
{
124+
result = false;
125+
}
126+
127+
return result
128+
? HealthCheckResult.Healthy($"AzureFileStorage {storageAccount.BlobStorageUri} is available")
129+
: HealthCheckResult.Unhealthy($"AzureFileStorage {storageAccount.BlobStorageUri} is unavailable");
130+
}, cacheDuration ?? builder.DefaultCacheDuration);
131+
132+
return builder;
133+
}
134+
135+
public static HealthCheckBuilder AddAzureQueueStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string queueName = null, TimeSpan? cacheDuration = null)
136+
{
137+
var credentials = new StorageCredentials(accountName, accountKey);
138+
var storageAccount = new CloudStorageAccount(credentials, true);
139+
return AddAzureQueueStorageCheck(builder, storageAccount, queueName, cacheDuration);
140+
}
141+
142+
public static HealthCheckBuilder AddAzureQueueStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string queueName = null, TimeSpan? cacheDuration = null)
143+
{
144+
builder.AddCheck($"AzureQueueStorageCheck {storageAccount.QueueStorageUri} {queueName}", async () =>
145+
{
146+
bool result;
147+
try
148+
{
149+
var queueClient = storageAccount.CreateCloudQueueClient();
150+
151+
var properties = await queueClient.GetServicePropertiesAsync().ConfigureAwait(false);
152+
153+
if (String.IsNullOrWhiteSpace(queueName))
154+
{
155+
var queue = queueClient.GetQueueReference(queueName);
156+
157+
result = await queue.ExistsAsync();
158+
}
159+
result = true;
160+
}
161+
catch (Exception)
162+
{
163+
result = false;
164+
}
165+
166+
return result
167+
? HealthCheckResult.Healthy($"AzureFileStorage {storageAccount.BlobStorageUri} is available")
168+
: HealthCheckResult.Unhealthy($"AzureFileStorage {storageAccount.BlobStorageUri} is unavailable");
169+
170+
}, cacheDuration ?? builder.DefaultCacheDuration);
171+
172+
return builder;
173+
}
174+
}
175+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard1.3</TargetFramework>
5+
<PackageTargetFallback>$(PackageTargetFallback);net46</PackageTargetFallback>
6+
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
7+
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
8+
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="1.0.2" />
21+
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
22+
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
23+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.3.0" />
24+
<PackageReference Include="WindowsAzure.Storage" Version="7.2.1" />
25+
</ItemGroup>
26+
27+
</Project>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Reflection;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.InteropServices;
7+
8+
// General Information about an assembly is controlled through the following
9+
// set of attributes. Change these attribute values to modify the information
10+
// associated with an assembly.
11+
[assembly: AssemblyConfiguration("")]
12+
[assembly: AssemblyCompany("")]
13+
[assembly: AssemblyProduct("HealthChecks.Azure")]
14+
[assembly: AssemblyTrademark("")]
15+
16+
// Setting ComVisible to false makes the types in this assembly not visible
17+
// to COM components. If you need to access a type in this assembly from
18+
// COM, set the ComVisible attribute to true on that type.
19+
[assembly: ComVisible(false)]
20+
21+
// The following GUID is for the ID of the typelib if this project is exposed to COM
22+
[assembly: Guid("0c4158b7-7153-4d2e-abfa-4ce07d44f75f")]

src/Services/Catalog/Catalog.API/Catalog.API.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
6868
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
6969
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
70+
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj" />
7071
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
7172
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
7273
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />

src/Services/Catalog/Catalog.API/Startup.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
using Microsoft.Extensions.HealthChecks;
2424
using Microsoft.Extensions.Logging;
2525
using Microsoft.Extensions.Options;
26+
using Microsoft.WindowsAzure.Storage;
27+
using Microsoft.WindowsAzure.Storage.Auth;
2628
using Polly;
2729
using RabbitMQ.Client;
2830
using System;
@@ -64,6 +66,13 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
6466
minutes = minutesParsed;
6567
}
6668
checks.AddSqlCheck("CatalogDb", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
69+
70+
var accountName = Configuration.GetValue<string>("AzureStorageAccountName");
71+
var accountKey = Configuration.GetValue<string>("AzureStorageAccountKey");
72+
if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
73+
{
74+
checks.AddAzureBlobStorageCheck(accountName, accountKey);
75+
}
6776
});
6877

6978
services.AddMvc(options =>
@@ -148,7 +157,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
148157
var container = new ContainerBuilder();
149158
container.Populate(services);
150159
return new AutofacServiceProvider(container.Build());
151-
160+
152161
}
153162

154163
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
@@ -186,7 +195,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
186195
private async Task WaitForSqlAvailabilityAsync(CatalogContext ctx, ILoggerFactory loggerFactory, IApplicationBuilder app, IHostingEnvironment env, int retries = 0)
187196
{
188197
var logger = loggerFactory.CreateLogger(nameof(Startup));
189-
var policy = CreatePolicy(retries, logger, nameof (WaitForSqlAvailabilityAsync));
198+
var policy = CreatePolicy(retries, logger, nameof(WaitForSqlAvailabilityAsync));
190199
await policy.ExecuteAsync(async () =>
191200
{
192201
await CatalogContextSeed.SeedAsync(app, env, loggerFactory);
@@ -222,7 +231,7 @@ private void RegisterEventBus(IServiceCollection services)
222231
return new EventBusServiceBus(serviceBusPersisterConnection, logger,
223232
eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
224233
});
225-
234+
226235
}
227236
else
228237
{

0 commit comments

Comments
 (0)