-
Notifications
You must be signed in to change notification settings - Fork 727
/
TemplateSpecModuleRegistry.cs
149 lines (117 loc) · 7.11 KB
/
TemplateSpecModuleRegistry.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.IO.Abstractions;
using Bicep.Core.Configuration;
using Bicep.Core.Diagnostics;
using Bicep.Core.Features;
using Bicep.Core.FileSystem;
using Bicep.Core.Modules;
using Bicep.Core.Semantics;
using Bicep.Core.SourceCode;
using Bicep.Core.Tracing;
using Bicep.Core.Utils;
namespace Bicep.Core.Registry
{
public readonly record struct TemplateSpecEntity(string Content);
public class TemplateSpecModuleRegistry : ExternalArtifactRegistry<TemplateSpecModuleReference, TemplateSpecEntity>
{
private readonly ITemplateSpecRepositoryFactory repositoryFactory;
private readonly IFeatureProvider featureProvider;
private readonly RootConfiguration configuration;
private readonly Uri parentModuleUri;
public TemplateSpecModuleRegistry(IFileResolver fileResolver, IFileSystem fileSystem, ITemplateSpecRepositoryFactory repositoryFactory, IFeatureProvider featureProvider, RootConfiguration configuration, Uri parentModuleUri)
: base(fileResolver, fileSystem)
{
this.repositoryFactory = repositoryFactory;
this.featureProvider = featureProvider;
this.configuration = configuration;
this.parentModuleUri = parentModuleUri;
}
public override string Scheme => ArtifactReferenceSchemes.TemplateSpecs;
public override RegistryCapabilities GetCapabilities(TemplateSpecModuleReference reference) => RegistryCapabilities.Default;
public override ResultWithDiagnostic<ArtifactReference> TryParseArtifactReference(ArtifactType artifactType, string? aliasName, string reference)
{
if (artifactType != ArtifactType.Module)
{
return new(x => x.UnsupportedArtifactType(artifactType));
}
if (!TemplateSpecModuleReference.TryParse(aliasName, reference, configuration, parentModuleUri).IsSuccess(out var @ref, out var failureBuilder))
{
return new(failureBuilder);
}
return new(@ref);
}
public override bool IsArtifactRestoreRequired(TemplateSpecModuleReference reference) =>
!this.FileResolver.FileExists(this.GetModuleEntryPointUri(reference));
public override Task PublishModule(TemplateSpecModuleReference reference, BinaryData compiled, BinaryData? bicepSources, string? documentationUri, string? description)
=> throw new NotSupportedException("Template Spec modules cannot be published.");
public override Task PublishProvider(TemplateSpecModuleReference reference, BinaryData typesTgz)
=> throw new NotSupportedException("Template Spec providers cannot be published.");
public override Task<bool> CheckArtifactExists(TemplateSpecModuleReference reference) => throw new NotSupportedException("Template Spec modules cannot be published.");
public override ResultWithDiagnostic<Uri> TryGetLocalArtifactEntryPointUri(TemplateSpecModuleReference reference)
{
var localUri = this.GetModuleEntryPointUri(reference);
return new(localUri);
}
public override async Task<IDictionary<ArtifactReference, DiagnosticBuilder.ErrorBuilderDelegate>> RestoreArtifacts(IEnumerable<TemplateSpecModuleReference> references)
{
var statuses = new Dictionary<ArtifactReference, DiagnosticBuilder.ErrorBuilderDelegate>();
foreach (var reference in references)
{
using var timer = new ExecutionTimer($"Restore module {reference.FullyQualifiedReference} to {GetArtifactDirectoryPath(reference)}");
try
{
var repository = this.repositoryFactory.CreateRepository(configuration, reference.SubscriptionId);
var templateSpecEntity = await repository.FindTemplateSpecByIdAsync(reference.TemplateSpecResourceId);
await this.WriteArtifactContentToCacheAsync(reference, templateSpecEntity);
}
catch (ExternalArtifactException templateSpecException)
{
statuses.Add(reference, x => x.ArtifactRestoreFailedWithMessage(reference.FullyQualifiedReference, templateSpecException.Message));
timer.OnFail(templateSpecException.Message);
}
catch (Exception exception)
{
if (exception.Message is { } message)
{
statuses.Add(reference, x => x.ArtifactRestoreFailedWithMessage(reference.FullyQualifiedReference, message));
timer.OnFail($"Unexpected exception {exception}: {message}");
return statuses;
}
statuses.Add(reference, x => x.ArtifactRestoreFailed(reference.FullyQualifiedReference));
timer.OnFail($"Unexpected exception {exception}.");
}
}
return statuses;
}
protected override void WriteArtifactContentToCache(TemplateSpecModuleReference reference, TemplateSpecEntity entity) =>
fileSystem.File.WriteAllText(this.GetModuleEntryPointPath(reference), entity.Content);
protected override string GetArtifactDirectoryPath(TemplateSpecModuleReference reference) => fileSystem.Path.Combine(
this.featureProvider.CacheRootDirectory,
this.Scheme,
reference.SubscriptionId.ToLowerInvariant(),
reference.ResourceGroupName.ToLowerInvariant(),
reference.TemplateSpecName.ToLowerInvariant(),
reference.Version.ToLowerInvariant());
protected override Uri GetArtifactLockFileUri(TemplateSpecModuleReference reference) => new(fileSystem.Path.Combine(this.GetArtifactDirectoryPath(reference), "lock"), UriKind.Absolute);
private string GetModuleEntryPointPath(TemplateSpecModuleReference reference) => fileSystem.Path.Combine(this.GetArtifactDirectoryPath(reference), "main.json");
private Uri GetModuleEntryPointUri(TemplateSpecModuleReference reference) => new(this.GetModuleEntryPointPath(reference), UriKind.Absolute);
public override async Task<IDictionary<ArtifactReference, DiagnosticBuilder.ErrorBuilderDelegate>> InvalidateArtifactsCache(IEnumerable<TemplateSpecModuleReference> references)
{
return await base.InvalidateArtifactsCacheInternal(references);
}
public override string? TryGetDocumentationUri(TemplateSpecModuleReference moduleReference) => null;
public override Task<string?> TryGetModuleDescription(ModuleSymbol module, TemplateSpecModuleReference moduleReference)
{
if (module.TryGetSemanticModel().TryUnwrap() is { } model)
{
return Task.FromResult(DescriptionHelper.TryGetFromSemanticModel(model));
}
return Task.FromResult<string?>(null);
}
public override ResultWithException<SourceArchive> TryGetSource(TemplateSpecModuleReference reference)
{
return new(new SourceNotAvailableException());
}
}
}