Skip to content

Commit 7760710

Browse files
committed
Add deploy update-redirects command to docs-assembler
1 parent 6a8201c commit 7760710

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

Directory.Packages.props

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
<PackageVersion Include="Amazon.Lambda.S3Events" Version="3.1.0" />
1414
<PackageVersion Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.4" />
1515
<PackageVersion Include="Amazon.Lambda.SQSEvents" Version="2.2.0" />
16+
<PackageVersion Include="AWSSDK.CloudFront" Version="4.0.0.10" />
17+
<PackageVersion Include="AWSSDK.CloudFrontKeyValueStore" Version="4.0.0.9" />
1618
<PackageVersion Include="AWSSDK.Core" Version="4.0.0.2" />
1719
<PackageVersion Include="AWSSDK.SQS" Version="4.0.0.1" />
1820
<PackageVersion Include="AWSSDK.S3" Version="4.0.0.1" />
@@ -70,4 +72,4 @@
7072
</PackageVersion>
7173
<PackageVersion Include="xunit.v3" Version="2.0.2" />
7274
</ItemGroup>
73-
</Project>
75+
</Project>

src/tooling/docs-assembler/Cli/DeployCommands.cs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44

55
using System.Diagnostics.CodeAnalysis;
66
using System.IO.Abstractions;
7+
using System.Text.Json;
78
using Actions.Core.Services;
9+
using Amazon.CloudFront;
10+
using Amazon.CloudFrontKeyValueStore;
11+
using Amazon.CloudFrontKeyValueStore.Model;
812
using Amazon.S3;
913
using Amazon.S3.Transfer;
1014
using ConsoleAppFramework;
1115
using Documentation.Assembler.Deploying;
16+
using Elastic.Documentation.Serialization;
1217
using Elastic.Documentation.Tooling.Diagnostics.Console;
18+
using Elastic.Documentation.Tooling.Filters;
1319
using Microsoft.Extensions.Logging;
1420

1521
namespace Documentation.Assembler.Cli;
@@ -94,4 +100,107 @@ public async Task<int> Apply(
94100
await collector.StopAsync(ctx);
95101
return collector.Errors;
96102
}
103+
104+
/// <summary>Refreshes the redirects mapping in Cloudfront's KeyValueStore</summary>
105+
/// <param name="environment">The environment to build</param>
106+
/// <param name="redirectsFile">Path to the redirects mapping pre-generated by docs-assembler</param>
107+
/// <param name="ctx"></param>
108+
[Command("update-redirects")]
109+
[ConsoleAppFilter<StopwatchFilter>]
110+
[ConsoleAppFilter<CatchExceptionFilter>]
111+
public async Task<int> UpdateRedirects(
112+
string environment,
113+
string redirectsFile = ".artifacts/assembly/redirects.json",
114+
Cancel ctx = default)
115+
{
116+
AssignOutputLogger();
117+
await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService)
118+
{
119+
NoHints = true
120+
}.StartAsync(ctx);
121+
122+
if (!File.Exists(redirectsFile))
123+
{
124+
collector.EmitError(redirectsFile, "Redirects mapping does not exist.");
125+
await collector.StopAsync(ctx);
126+
return collector.Errors;
127+
}
128+
129+
ConsoleApp.Log("Parsing redirects mapping");
130+
var jsonContent = await File.ReadAllTextAsync(redirectsFile, ctx);
131+
var sourcedRedirects = JsonSerializer.Deserialize(jsonContent, SourceGenerationContext.Default.FrozenDictionaryStringString);
132+
133+
if (sourcedRedirects is null)
134+
{
135+
collector.EmitError(redirectsFile, "Redirects mapping is invalid.");
136+
await collector.StopAsync(ctx);
137+
return collector.Errors;
138+
}
139+
140+
var kvsName = $"elastic-docs-v3-{environment}-redirects-kvs";
141+
142+
var cfClient = new AmazonCloudFrontClient();
143+
var kvsClient = new AmazonCloudFrontKeyValueStoreClient();
144+
145+
ConsoleApp.Log("Describing KVS");
146+
var describeResponse = await cfClient.DescribeKeyValueStoreAsync(new Amazon.CloudFront.Model.DescribeKeyValueStoreRequest()
147+
{
148+
Name = kvsName
149+
}, ctx);
150+
151+
var kvsArn = describeResponse.KeyValueStore.ARN;
152+
var eTag = describeResponse.ETag;
153+
var existingRedirects = new HashSet<string>();
154+
155+
var listKeysRequest = new ListKeysRequest { KvsARN = kvsArn };
156+
ListKeysResponse listKeysResponse;
157+
158+
do
159+
{
160+
listKeysResponse = await kvsClient.ListKeysAsync(listKeysRequest, ctx);
161+
foreach (var item in listKeysResponse.Items)
162+
_ = existingRedirects.Add(item.Key);
163+
listKeysRequest.NextToken = listKeysResponse.NextToken;
164+
}
165+
while (!string.IsNullOrEmpty(listKeysResponse.NextToken));
166+
167+
var toPut = sourcedRedirects
168+
.Select(kvp => new PutKeyRequestListItem { Key = kvp.Key, Value = kvp.Value })
169+
.ToList();
170+
var toDelete = existingRedirects
171+
.Except(sourcedRedirects.Keys)
172+
.Select(k => new DeleteKeyRequestListItem { Key = k })
173+
.ToList();
174+
175+
ConsoleApp.Log("Updating redirects in KVS");
176+
const int batchSize = 500;
177+
178+
for (var i = 0; i < toPut.Count; i += batchSize)
179+
{
180+
var batch = toPut.Skip(i).Take(batchSize).ToList();
181+
var update = await kvsClient.UpdateKeysAsync(new UpdateKeysRequest
182+
{
183+
KvsARN = kvsArn,
184+
IfMatch = eTag,
185+
Puts = batch
186+
}, ctx);
187+
eTag = update.ETag;
188+
}
189+
190+
for (var i = 0; i < toDelete.Count; i += batchSize)
191+
{
192+
var batch = toDelete.Skip(i).Take(batchSize).ToList();
193+
var update = await kvsClient.UpdateKeysAsync(new UpdateKeysRequest
194+
{
195+
KvsARN = kvsArn,
196+
IfMatch = eTag,
197+
Deletes = batch
198+
}, ctx);
199+
eTag = update.ETag;
200+
}
201+
202+
await collector.StopAsync(ctx);
203+
return collector.Errors;
204+
}
205+
97206
}

src/tooling/docs-assembler/docs-assembler.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
</PropertyGroup>
1818

1919
<ItemGroup>
20+
<PackageReference Include="AWSSDK.CloudFront" />
21+
<PackageReference Include="AWSSDK.CloudFrontKeyValueStore" />
2022
<PackageReference Include="AWSSDK.S3"/>
2123
<PackageReference Include="ConsoleAppFramework.Abstractions"/>
2224
<PackageReference Include="ConsoleAppFramework" />

0 commit comments

Comments
 (0)