diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AutoRest.Generator.AzureResourceSchema.Tests.csproj b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AutoRest.Generator.AzureResourceSchema.Tests.csproj
index 242444dbc8c08..dda8fa1fd6407 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AutoRest.Generator.AzureResourceSchema.Tests.csproj
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AutoRest.Generator.AzureResourceSchema.Tests.csproj
@@ -34,6 +34,10 @@
4
+
+ ..\..\..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll
+ True
+
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AzureResourceSchemaCodeGeneratorTests.cs b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AzureResourceSchemaCodeGeneratorTests.cs
index 4591537496b3e..c5c37c0a235f2 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AzureResourceSchemaCodeGeneratorTests.cs
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AzureResourceSchemaCodeGeneratorTests.cs
@@ -2,7 +2,10 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using Microsoft.Rest.Generator.ClientModel;
-using System;
+using Microsoft.Rest.Generator.Utilities;
+using Newtonsoft.Json.Linq;
+using System.Linq;
+using System.Threading.Tasks;
using Xunit;
namespace Microsoft.Rest.Generator.AzureResourceSchema.Tests
@@ -11,46 +14,142 @@ namespace Microsoft.Rest.Generator.AzureResourceSchema.Tests
public class AzureResourceSchemaCodeGeneratorTests
{
[Fact]
- public void DescriptionThrowsException()
+ public void Description()
{
Assert.Equal("Azure Resource Schema generator", CreateGenerator().Description);
}
[Fact]
- public void ImplementationFileExtensionThrowsException()
+ public void ImplementationFileExtension()
{
Assert.Equal(".json", CreateGenerator().ImplementationFileExtension);
}
[Fact]
- public void NameThrowsException()
+ public void Name()
{
Assert.Equal("AzureResourceSchema", CreateGenerator().Name);
}
[Fact]
- public void UsageInstructionsThrowsException()
+ public void UsageInstructionsWithNoOutputFileSetting()
{
- Assert.Equal("MOCK USAGE INSTRUCTIONS", CreateGenerator().UsageInstructions);
+ AzureResourceSchemaCodeGenerator codeGen = CreateGenerator();
+ Assert.Equal("Your Azure Resource Schema can be found at " + codeGen.SchemaPath, codeGen.UsageInstructions);
}
[Fact]
- public void GenerateThrowsException()
+ public void UsageInstructionsWithOutputFileSetting()
{
- ServiceClient serviceClient = new ServiceClient();
- Assert.Throws(() => { CreateGenerator().Generate(serviceClient); });
+ Settings settings = new Settings()
+ {
+ OutputFileName = "spam.json"
+ };
+ AzureResourceSchemaCodeGenerator codeGen = CreateGenerator(settings);
+
+ Assert.Equal("Your Azure Resource Schema can be found at " + codeGen.SchemaPath, codeGen.UsageInstructions);
+ }
+
+ [Fact]
+ public async void GenerateWithEmptyServiceClient()
+ {
+ await TestGenerate(new string[0],
+ @"{
+ 'id': 'http://schema.management.azure.com/schemas//Microsoft.Storage.json#',
+ '$schema': 'http://json-schema.org/draft-04/schema#',
+ 'title': 'Microsoft.Storage',
+ 'description': 'Microsoft Storage Resource Types',
+ 'resourceDefinitions': { }
+ }");
+ }
+
+ [Fact]
+ public async void GenerateWithServiceClientWithOneType()
+ {
+ await TestGenerate(new string[]
+ {
+ "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Mock.Provider/mockType"
+ },
+ @"{
+ 'id': 'http://schema.management.azure.com/schemas//Microsoft.Storage.json#',
+ '$schema': 'http://json-schema.org/draft-04/schema#',
+ 'title': 'Microsoft.Storage',
+ 'description': 'Microsoft Storage Resource Types',
+ 'resourceDefinitions': {
+ 'mockType': {
+ }
+ }
+ }");
+ }
+
+ [Fact]
+ public async void GenerateWithServiceClientWithTwoTypes()
+ {
+ await TestGenerate(new string[]
+ {
+ "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Mock.Provider/mockType1",
+ "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Mock.Provider/mockType2"
+ },
+ @"{
+ 'id': 'http://schema.management.azure.com/schemas//Microsoft.Storage.json#',
+ '$schema': 'http://json-schema.org/draft-04/schema#',
+ 'title': 'Microsoft.Storage',
+ 'description': 'Microsoft Storage Resource Types',
+ 'resourceDefinitions': {
+ 'mockType1': {
+ },
+ 'mockType2': {
+ }
+ }
+ }");
}
[Fact]
- public void NormalizeClientModelThrowsException()
+ public void NormalizeClientModelDoesNothing()
{
ServiceClient serviceClient = new ServiceClient();
- Assert.Throws(() => { CreateGenerator().NormalizeClientModel(serviceClient); });
+ CreateGenerator().NormalizeClientModel(serviceClient);
+
+ // Nothing happens
}
private static AzureResourceSchemaCodeGenerator CreateGenerator()
{
- return new AzureResourceSchemaCodeGenerator(new Settings());
+ return CreateGenerator(new Settings());
+ }
+ private static AzureResourceSchemaCodeGenerator CreateGenerator(Settings settings)
+ {
+ return new AzureResourceSchemaCodeGenerator(settings);
+ }
+
+ private static async Task TestGenerate(string[] methodUrls, string expectedJsonString)
+ {
+ MemoryFileSystem fileSystem = new MemoryFileSystem();
+
+ Settings settings = new Settings();
+ settings.FileSystem = fileSystem;
+
+ ServiceClient serviceClient = new ServiceClient();
+ foreach(string methodUrl in methodUrls)
+ {
+ serviceClient.Methods.Add(new Method()
+ {
+ Url = methodUrl
+ });
+ }
+ await CreateGenerator(settings).Generate(serviceClient);
+
+ Assert.Equal(2, fileSystem.VirtualStore.Count);
+
+ string folderPath = fileSystem.VirtualStore.Keys.First();
+ Assert.Equal("Folder", fileSystem.VirtualStore[folderPath].ToString());
+
+ JObject expectedJSON = JObject.Parse(expectedJsonString);
+
+ string fileContents = fileSystem.VirtualStore[fileSystem.VirtualStore.Keys.Skip(1).First()].ToString();
+ JObject actualJson = JObject.Parse(fileContents);
+
+ Assert.Equal(expectedJSON, actualJson);
}
}
}
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/packages.config b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/packages.config
index 64fb5d7b3b792..c2c499b747eb4 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/packages.config
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/packages.config
@@ -1,5 +1,6 @@
+
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj
index f934e945c6e9e..5b00abb1fff44 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj
@@ -20,6 +20,10 @@
4
+
+ ..\..\..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll
+ True
+
@@ -44,5 +48,8 @@
CustomDictionary.xml
+
+
+
\ No newline at end of file
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs
index e879d0b9bd2f6..5d5df37291ca7 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs
@@ -2,18 +2,33 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using Microsoft.Rest.Generator.ClientModel;
+using Newtonsoft.Json;
using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Rest.Generator.AzureResourceSchema
{
public class AzureResourceSchemaCodeGenerator : CodeGenerator
{
+ private const string resourceMethodPrefix = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/";
+
public AzureResourceSchemaCodeGenerator(Settings settings)
: base(settings)
{
}
+ public string SchemaPath
+ {
+ get
+ {
+ string defaultSchemaFileName = Path.GetFileNameWithoutExtension(Settings.Input) + ".schema.json";
+ return Path.Combine(Settings.OutputDirectory, Settings.OutputFileName ?? defaultSchemaFileName);
+ }
+ }
+
public override string Description
{
get { return "Azure Resource Schema generator"; }
@@ -31,17 +46,145 @@ public override string Name
public override string UsageInstructions
{
- get { return "MOCK USAGE INSTRUCTIONS"; }
+ get { return "Your Azure Resource Schema can be found at " + SchemaPath; }
}
- public override Task Generate(ServiceClient serviceClient)
+ public override void NormalizeClientModel(ServiceClient serviceClient)
{
- throw new NotImplementedException();
}
- public override void NormalizeClientModel(ServiceClient serviceClient)
+ public override async Task Generate(ServiceClient serviceClient)
{
- throw new NotImplementedException();
+ StringWriter stringWriter = new StringWriter();
+ using (JsonTextWriter writer = new JsonTextWriter(stringWriter))
+ {
+ writer.Formatting = Formatting.Indented;
+ writer.Indentation = 2;
+ writer.IndentChar = ' ';
+
+ string resourceProvider = GetResourceProvider(serviceClient);
+ IEnumerable resourceFullTypes = GetResourceFullTypes(serviceClient);
+
+ WriteObject(writer, () => {
+ WriteProperty(writer, "id", string.Format("http://schema.management.azure.com/schemas/{0}/Microsoft.Storage.json#", serviceClient.ApiVersion));
+ WriteProperty(writer, "$schema", "http://json-schema.org/draft-04/schema#");
+ WriteProperty(writer, "title", resourceProvider);
+ WriteProperty(writer, "description", resourceProvider.Replace('.', ' ') + " Resource Types");
+ WriteProperty(writer, "resourceDefinitions", () => {
+ foreach (string resourceFullType in resourceFullTypes)
+ {
+ string resourceShortType = resourceFullType.Substring(resourceFullType.IndexOf('/') + 1);
+
+ WriteProperty(writer, resourceShortType, () => {
+ WriteProperty(writer, "type", "object");
+ WriteProperty(writer, "properties", () => {
+ WriteProperty(writer, "type", () => {
+ WriteProperty(writer, "enum", new string[] {
+ resourceFullType
+ });
+ });
+ WriteProperty(writer, "apiVersion", () => {
+ WriteProperty(writer, "enum", new string[] {
+ serviceClient.ApiVersion
+ });
+ });
+ WriteProperty(writer, "properties", () => {
+ WriteProperty(writer, "type", "object");
+ WriteProperty(writer, "properties", () => {
+ });
+ WriteProperty(writer, "required", new string[0]);
+ });
+ });
+ WriteProperty(writer, "required", new string[] {
+ "type",
+ "apiVersion",
+ "properties",
+ "location"
+ });
+ WriteProperty(writer, "description", resourceFullType);
+ });
+ }
+ });
+ });
+ }
+
+ await Write(stringWriter.ToString(), SchemaPath);
+ }
+
+ private static IEnumerable GetResourceMethods(ServiceClient serviceClient)
+ {
+ return GetResourceMethods(serviceClient.Methods);
+ }
+
+ private static IEnumerable GetResourceMethods(IEnumerable methods)
+ {
+ return methods.Where(m => m.Url.StartsWith(resourceMethodPrefix));
+ }
+
+ private static IEnumerable GetResourceMethodUrisAfterPrefix(ServiceClient serviceClient)
+ {
+ IEnumerable resourceMethods = GetResourceMethods(serviceClient);
+ IEnumerable resourceMethodUris = resourceMethods.Select(rm => rm.Url);
+ return resourceMethodUris.Select(rmu => rmu.Substring(resourceMethodPrefix.Length));
+ }
+
+ private static string GetResourceProvider(ServiceClient serviceClient)
+ {
+ IEnumerable resourceMethodUrisAfterPrefix = GetResourceMethodUrisAfterPrefix(serviceClient);
+ return resourceMethodUrisAfterPrefix.Select(rmuap => rmuap.Substring(0, rmuap.IndexOf('/'))).Distinct().Single();
+ }
+
+ private static IEnumerable GetResourceFullTypes(ServiceClient serviceClient)
+ {
+ IEnumerable resourceMethodUrisAfterPrefix = GetResourceMethodUrisAfterPrefix(serviceClient);
+ return resourceMethodUrisAfterPrefix.Select(rmuap =>
+ {
+ int forwardSlashAfterProvider = rmuap.IndexOf('/');
+ int forwardSlashAfterType = rmuap.IndexOf('/', forwardSlashAfterProvider + 1);
+ int startIndex = forwardSlashAfterProvider + 1;
+ if (forwardSlashAfterType == -1)
+ {
+ return rmuap;
+ }
+ else
+ {
+ return rmuap.Substring(0, forwardSlashAfterType);
+ }
+ }).Distinct();
+ }
+
+ private static void WriteObject(JsonTextWriter writer, Action writeObjectContents)
+ {
+ writer.WriteStartObject();
+
+ writeObjectContents.Invoke();
+
+ writer.WriteEndObject();
+ }
+
+ private static void WriteProperty(JsonTextWriter writer, string propertyName, string propertyValue)
+ {
+ writer.WritePropertyName(propertyName);
+ writer.WriteValue(propertyValue);
+ }
+
+ private static void WriteProperty(JsonTextWriter writer, string propertyName, Action writeObjectContents)
+ {
+ writer.WritePropertyName(propertyName);
+ WriteObject(writer, writeObjectContents);
+ }
+
+ private static void WriteProperty(JsonTextWriter writer, string propertyName, string[] writeArrayContents)
+ {
+ writer.WritePropertyName(propertyName);
+ writer.WriteStartArray();
+
+ foreach (string value in writeArrayContents)
+ {
+ writer.WriteValue(value);
+ }
+
+ writer.WriteEndArray();
}
}
}
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/packages.config b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/packages.config
new file mode 100644
index 0000000000000..505e58836baea
--- /dev/null
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file