Skip to content

Commit

Permalink
Merge pull request #372 from Azure/ar/issue-275-fix
Browse files Browse the repository at this point in the history
Lookup and apply serviceUrl when specification.yaml file is commited by itself v2
  • Loading branch information
waelkdouh authored Dec 1, 2023
2 parents f689b6e + 52e83f2 commit 299b8bd
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 15 deletions.
75 changes: 64 additions & 11 deletions tools/code/publisher/Api.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace publisher;

internal static class Api
{
public static async ValueTask ProcessDeletedArtifacts(IReadOnlyCollection<FileInfo> files, JsonObject configurationJson, ServiceDirectory serviceDirectory, ServiceUri serviceUri, PutRestResource putRestResource, DeleteRestResource deleteRestResource, ILogger logger, CancellationToken cancellationToken)
public static async ValueTask ProcessDeletedArtifacts(IReadOnlyCollection<FileInfo> files, JsonObject configurationJson, ServiceDirectory serviceDirectory, ServiceUri serviceUri, GetRestResource getRestResource, PutRestResource putRestResource, DeleteRestResource deleteRestResource, ILogger logger, CancellationToken cancellationToken)
{
var configurationApis = GetConfigurationApis(configurationJson);

Expand All @@ -27,7 +27,7 @@ await GetApisFromFiles(files, serviceDirectory)
secondKeySelector: configurationArtifact => configurationArtifact.ApiName,
firstSelector: api => (api.ApiName, api.InformationFile, api.SpecificationFile, ConfigurationApiJson: (JsonObject?)null),
bothSelector: (file, configurationArtifact) => (file.ApiName, file.InformationFile, file.SpecificationFile, ConfigurationApiJson: configurationArtifact.Json))
.ForEachParallel(async artifact => await ProcessDeletedApi(artifact.ApiName, artifact.InformationFile, artifact.SpecificationFile, artifact.ConfigurationApiJson, serviceDirectory, serviceUri, putRestResource, deleteRestResource, logger, cancellationToken),
.ForEachParallel(async artifact => await ProcessDeletedApi(artifact.ApiName, artifact.InformationFile, artifact.SpecificationFile, artifact.ConfigurationApiJson, serviceDirectory, serviceUri, getRestResource, putRestResource, deleteRestResource, logger, cancellationToken),
cancellationToken);
}

Expand Down Expand Up @@ -192,7 +192,7 @@ private static ApiName GetApiName(ApiSpecificationFile specificationFile)
return new(specificationFile.ApiDirectory.GetName());
}

private static async ValueTask ProcessDeletedApi(ApiName apiName, ApiInformationFile? deletedApiInformationFile, ApiSpecificationFile? deletedSpecificationFile, JsonObject? configurationApiJson, ServiceDirectory serviceDirectory, ServiceUri serviceUri, PutRestResource putRestResource, DeleteRestResource deleteRestResource, ILogger logger, CancellationToken cancellationToken)
private static async ValueTask ProcessDeletedApi(ApiName apiName, ApiInformationFile? deletedApiInformationFile, ApiSpecificationFile? deletedSpecificationFile, JsonObject? configurationApiJson, ServiceDirectory serviceDirectory, ServiceUri serviceUri, GetRestResource getRestResource, PutRestResource putRestResource, DeleteRestResource deleteRestResource, ILogger logger, CancellationToken cancellationToken)
{
switch (deletedApiInformationFile, deletedSpecificationFile)
{
Expand All @@ -208,7 +208,7 @@ private static async ValueTask ProcessDeletedApi(ApiName apiName, ApiInformation
}
else
{
await PutApi(apiName, existingInformationFile, specificationFile: null, configurationApiJson, serviceUri, putRestResource, logger, cancellationToken);
await PutApi(apiName, existingInformationFile, specificationFile: null, configurationApiJson, serviceUri, getRestResource, putRestResource, logger, cancellationToken);
}

return;
Expand All @@ -221,7 +221,7 @@ private static async ValueTask ProcessDeletedApi(ApiName apiName, ApiInformation
}
else
{
await PutApi(apiName, apiInformationFile: null, existingSpecificationFile, configurationApiJson, serviceUri, putRestResource, logger, cancellationToken);
await PutApi(apiName, apiInformationFile: null, existingSpecificationFile, configurationApiJson, serviceUri, getRestResource, putRestResource, logger, cancellationToken);
}

return;
Expand Down Expand Up @@ -260,7 +260,7 @@ public static ApiUri GetApiUri(ApiName apiName, ServiceUri serviceUri)
.FirstOrDefault() : null;
}

private static async ValueTask PutApi(ApiName apiName, ApiInformationFile? apiInformationFile, ApiSpecificationFile? specificationFile, JsonObject? configurationApiJson, ServiceUri serviceUri, PutRestResource putRestResource, ILogger logger, CancellationToken cancellationToken)
private static async ValueTask PutApi(ApiName apiName, ApiInformationFile? apiInformationFile, ApiSpecificationFile? specificationFile, JsonObject? configurationApiJson, ServiceUri serviceUri, GetRestResource getRestResource, PutRestResource putRestResource, ILogger logger, CancellationToken cancellationToken)
{
if (apiInformationFile is null && specificationFile is null && configurationApiJson is null)
{
Expand All @@ -278,7 +278,7 @@ private static async ValueTask PutApi(ApiName apiName, ApiInformationFile? apiIn
putUri = putUri.SetQueryParam("import", "true").ToUri();
}

var apiJson = await GetApiJson(apiName, apiInformationFile, specificationFile, configurationApiJson, cancellationToken);
var apiJson = await GetApiJson(apiName, apiInformationFile, specificationFile, configurationApiJson, serviceUri, getRestResource, cancellationToken);
await putRestResource(putUri, apiJson, cancellationToken);

// Handle GraphQL specification
Expand All @@ -288,7 +288,7 @@ private static async ValueTask PutApi(ApiName apiName, ApiInformationFile? apiIn
}
}

private static async ValueTask<JsonObject> GetApiJson(ApiName apiName, ApiInformationFile? apiInformationFile, ApiSpecificationFile? specificationFile, JsonObject? configurationApiJson, CancellationToken cancellationToken)
private static async ValueTask<JsonObject> GetApiJson(ApiName apiName, ApiInformationFile? apiInformationFile, ApiSpecificationFile? specificationFile, JsonObject? configurationApiJson, ServiceUri serviceUri, GetRestResource getRestResource, CancellationToken cancellationToken)
{
var apiJson = new JsonObject();

Expand All @@ -301,6 +301,13 @@ private static async ValueTask<JsonObject> GetApiJson(ApiName apiName, ApiInform
if (specificationFile is not null and (ApiSpecificationFile.Wadl or ApiSpecificationFile.Wsdl or ApiSpecificationFile.OpenApi))
{
var specificationJson = await GetApiSpecificationJson(specificationFile, cancellationToken);
//If there is not apiInformationFile, retrieve the serviceUrl from the API's service.
if (apiInformationFile is null)
{
// Temporary work around to address the fact the management API will update the serviceURL to the management API's URL.
var propertyName = "serviceUrl";
apiJson = await GetPropertiesPropertyFronJson(apiName, propertyName, serviceUri, getRestResource, cancellationToken);
}
apiJson = apiJson.Merge(specificationJson);
}

Expand All @@ -317,6 +324,52 @@ private static async ValueTask<JsonObject> GetApiJson(ApiName apiName, ApiInform
return apiJson;
}

/// <summary>
/// This method will call the REST endpoint for the passed in API Name. It then will take that response, parse the properties object
/// and return the propertyName property.
/// </summary>
/// <param name="apiName">Name of the api</param>
/// <param name="propertyName">Name of the property you want to get the value of from the properties object</param>
/// <param name="serviceUri">URI of the endpoint you need to get the json from</param>
/// <param name="getRestResource">Delegate to call the REST endpoint based on the apiName</param>
/// <param name="cancellationToken">Cancellation Token</param>
/// <returns></returns>
static async Task<JsonObject> GetPropertiesPropertyFronJson(ApiName apiName, String propertyName, ServiceUri serviceUri, GetRestResource getRestResource, CancellationToken cancellationToken)
{
// If the API does not have an information file, retrieve the serviceUrl from the API's service.
var apiUri = GetApiUri(apiName, serviceUri);
var apiJsonObject = await getRestResource(apiUri.Uri, cancellationToken);
var propertiesNode = apiJsonObject.GetNullableProperty("properties");

if (propertiesNode != null && propertiesNode is JsonObject propertiesObject)
{
var apiServiceUrlNode = propertiesObject.GetNullableProperty(propertyName);

if (apiServiceUrlNode != null && apiServiceUrlNode is JsonValue apiServiceUrlValue)
{
var apiServiceUrl = apiServiceUrlValue.ToString();

JsonObject apiJson = new JsonObject
{
["properties"] = new JsonObject
{
["serviceUrl"] = apiServiceUrl
}
};

return apiJson;
}
else
{
throw new InvalidOperationException($"Could not find property '{propertyName}' in the properties object of the JSON object.");
}
}
else
{
throw new InvalidOperationException($"Could not find the properties object in JSON object.");
}
}

private static async ValueTask<JsonObject> GetApiSpecificationJson(ApiSpecificationFile specificationFile, CancellationToken cancellationToken)
{
var json = new JsonObject
Expand Down Expand Up @@ -378,7 +431,7 @@ private static async ValueTask PutGraphQlSchema(ApiUri apiUri, ApiSpecificationF
await putRestResource(schemaUri.Uri, json, cancellationToken);
}

public static async ValueTask ProcessArtifactsToPut(IReadOnlyCollection<FileInfo> files, JsonObject configurationJson, ServiceDirectory serviceDirectory, ServiceUri serviceUri, PutRestResource putRestResource, ILogger logger, CancellationToken cancellationToken)
public static async ValueTask ProcessArtifactsToPut(IReadOnlyCollection<FileInfo> files, JsonObject configurationJson, ServiceDirectory serviceDirectory, ServiceUri serviceUri, GetRestResource getRestResource, PutRestResource putRestResource, ILogger logger, CancellationToken cancellationToken)
{
var configurationApis = GetConfigurationApis(configurationJson);

Expand All @@ -388,7 +441,7 @@ await GetApisFromFiles(files, serviceDirectory)
secondKeySelector: configurationArtifact => configurationArtifact.ApiName,
firstSelector: api => (api.ApiName, api.InformationFile, api.SpecificationFile, ConfigurationApiJson: (JsonObject?)null),
bothSelector: (fileApi, configurationArtifact) => (fileApi.ApiName, fileApi.InformationFile, fileApi.SpecificationFile, ConfigurationApiJson: configurationArtifact.Json))
.ForEachParallel(async api => await PutApi(api.ApiName, api.InformationFile, api.SpecificationFile, api.ConfigurationApiJson, serviceUri, putRestResource, logger, cancellationToken),
.ForEachParallel(async api => await PutApi(api.ApiName, api.InformationFile, api.SpecificationFile, api.ConfigurationApiJson, serviceUri, getRestResource, putRestResource, logger, cancellationToken),
cancellationToken);
}
}
}
1 change: 1 addition & 0 deletions tools/code/publisher/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace publisher;

internal delegate IAsyncEnumerable<JsonObject> ListRestResources(Uri uri, CancellationToken cancellationToken);
internal delegate ValueTask<JsonObject> GetRestResource(Uri uri, CancellationToken cancellationToken);

internal delegate ValueTask PutRestResource(Uri uri, JsonObject jsonObject, CancellationToken cancellationToken);

Expand Down
26 changes: 26 additions & 0 deletions tools/code/publisher/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ private static void ConfigureServices(IServiceCollection services)
.AddSingleton(GetHttpPipeline)
.AddSingleton(GetDeleteRestResource)
.AddSingleton(GetListRestResources)
.AddSingleton(GetGetRestResource)
.AddSingleton(GetPutRestResource)
.AddSingleton(GetPublisherParameters)
.AddHostedService<Publisher>();
Expand Down Expand Up @@ -149,6 +150,30 @@ private static ListRestResources GetListRestResources(IServiceProvider provider)
};
}

private static GetRestResource GetGetRestResource(IServiceProvider provider)
{
var pipeline = provider.GetRequiredService<HttpPipeline>();
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(GetRestResource));

return async (uri, cancellationToken) =>
{
logger.LogDebug("Beginning request to get REST resource at URI {uri}...", uri);

var json = await pipeline.GetJsonObject(uri, cancellationToken);

if (logger.IsEnabled(LogLevel.Trace))
{
logger.LogTrace("Successfully retrieved REST resource {json} at URI {uri}.", json.ToJsonString(), uri);
}
else
{
logger.LogDebug("Successfully retrieved REST resource at URI {uri}.", uri);
}

return json;
};
}

private static PutRestResource GetPutRestResource(IServiceProvider provider)
{
var pipeline = provider.GetRequiredService<HttpPipeline>();
Expand Down Expand Up @@ -184,6 +209,7 @@ private static Publisher.Parameters GetPublisherParameters(IServiceProvider prov
ConfigurationJson = GetConfigurationJson(configuration),
DeleteRestResource = provider.GetRequiredService<DeleteRestResource>(),
ListRestResources = provider.GetRequiredService<ListRestResources>(),
GetRestResource = provider.GetRequiredService<GetRestResource>(),
Logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(Publisher)),
PutRestResource = provider.GetRequiredService<PutRestResource>(),
ServiceDirectory = GetServiceDirectory(configuration),
Expand Down
4 changes: 4 additions & 0 deletions tools/code/publisher/Publisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ internal record Parameters
public required DeleteRestResource DeleteRestResource { get; init; }
public required ILogger Logger { get; init; }
public required ListRestResources ListRestResources { get; init; }
public required GetRestResource GetRestResource { get; init; }
public required PutRestResource PutRestResource { get; init; }
public required ServiceDirectory ServiceDirectory { get; init; }
public required ServiceUri ServiceUri { get; init; }
Expand Down Expand Up @@ -86,6 +87,7 @@ await Service.ProcessArtifactsToPut(files,
publisherParameters.ServiceDirectory,
publisherParameters.ServiceUri,
publisherParameters.ListRestResources,
publisherParameters.GetRestResource,
publisherParameters.PutRestResource,
publisherParameters.DeleteRestResource,
logger,
Expand Down Expand Up @@ -141,6 +143,7 @@ await Service.ProcessDeletedArtifacts(deletedCommitIdFiles,
publisherParameters.ServiceDirectory,
publisherParameters.ServiceUri,
publisherParameters.ListRestResources,
publisherParameters.GetRestResource,
publisherParameters.PutRestResource,
publisherParameters.DeleteRestResource,
publisherParameters.Logger,
Expand All @@ -154,6 +157,7 @@ await Service.ProcessArtifactsToPut(commitIdFilesToPut,
publisherParameters.ServiceDirectory,
publisherParameters.ServiceUri,
publisherParameters.ListRestResources,
publisherParameters.GetRestResource,
publisherParameters.PutRestResource,
publisherParameters.DeleteRestResource,
publisherParameters.Logger,
Expand Down
Loading

0 comments on commit 299b8bd

Please sign in to comment.