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 9be4197827..be1ade26d4 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AutoRest.Generator.AzureResourceSchema.Tests.csproj
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema.Tests/AutoRest.Generator.AzureResourceSchema.Tests.csproj
@@ -47,21 +47,6 @@
-
- ..\..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
- True
-
-
- ..\..\..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll
- True
-
-
- ..\..\..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll
- True
-
-
- ..\..\..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll
-
..\..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
True
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj
index 5385b9c337..e7549af2d2 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AutoRest.Generator.AzureResourceSchema.csproj
@@ -30,6 +30,8 @@
+
+
Properties\AssemblyVersionInfo.cs
@@ -47,7 +49,7 @@
- CustomDictionary.xml
+ CustomDictionary.xml
@@ -81,6 +83,7 @@
+
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs
index 69d8deb74c..ed8daccd72 100644
--- a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/AzureResourceSchemaCodeGenerator.cs
@@ -5,6 +5,7 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@@ -13,8 +14,6 @@ namespace Microsoft.Rest.Generator.AzureResourceSchema
{
public class AzureResourceSchemaCodeGenerator : CodeGenerator
{
- private const string resourceMethodPrefix = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/";
-
public AzureResourceSchemaCodeGenerator(Settings settings)
: base(settings)
{
@@ -55,102 +54,111 @@ public override void NormalizeClientModel(ServiceClient serviceClient)
public override async Task Generate(ServiceClient serviceClient)
{
- StringWriter stringWriter = new StringWriter();
- using (JsonTextWriter writer = new JsonTextWriter(stringWriter))
+ try
{
- 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}/{1}.json#", serviceClient.ApiVersion, resourceProvider));
- 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);
- });
- }
- });
- });
- }
+ StringWriter stringWriter = new StringWriter();
+ using (JsonTextWriter writer = new JsonTextWriter(stringWriter))
+ {
+ writer.Formatting = Formatting.Indented;
+ writer.Indentation = 2;
+ writer.IndentChar = ' ';
- await Write(stringWriter.ToString(), SchemaPath);
- }
+ Schema schema = Schema.Parse(serviceClient);
- private static IEnumerable GetResourceMethods(ServiceClient serviceClient)
- {
- return GetResourceMethods(serviceClient.Methods);
- }
+ WriteSchema(writer, schema);
+ }
- private static IEnumerable GetResourceMethods(IEnumerable methods)
- {
- return methods.Where(m => m.Url.StartsWith(resourceMethodPrefix));
+ await Write(stringWriter.ToString(), SchemaPath);
+ }
+ catch (Exception)
+ {
+ Debugger.Break();
+ }
}
- private static IEnumerable GetResourceMethodUrisAfterPrefix(ServiceClient serviceClient)
+ private static void WriteSchema(JsonTextWriter writer, Schema schema)
{
- IEnumerable resourceMethods = GetResourceMethods(serviceClient);
- IEnumerable resourceMethodUris = resourceMethods.Select(rm => rm.Url);
- return resourceMethodUris.Select(rmu => rmu.Substring(resourceMethodPrefix.Length));
+ WriteObject(writer, () =>
+ {
+ WriteProperty(writer, "id", schema.Id);
+ WriteProperty(writer, "$schema", schema.SchemaUri);
+ WriteProperty(writer, "title", schema.Title);
+ WriteProperty(writer, "description", schema.Description);
+ WriteProperty(writer, "resourceDefinitions", () =>
+ {
+ foreach (Resource resource in schema.Resources)
+ {
+ WriteResource(writer, resource);
+ }
+ });
+ });
}
- private static string GetResourceProvider(ServiceClient serviceClient)
+ private static void WriteResource(JsonTextWriter writer, Resource resource)
{
- IEnumerable resourceMethodUrisAfterPrefix = GetResourceMethodUrisAfterPrefix(serviceClient);
- return resourceMethodUrisAfterPrefix.Select(rmuap => rmuap.Substring(0, rmuap.IndexOf('/'))).Distinct().Single();
+ WriteProperty(writer, resource.Name, () =>
+ {
+ WriteProperty(writer, "type", "object");
+ WriteProperty(writer, "properties", () =>
+ {
+ WriteProperty(writer, "type", () =>
+ {
+ WriteProperty(writer, "enum", new string[]
+ {
+ resource.Type
+ });
+ });
+
+ WriteProperty(writer, "apiVersion", () =>
+ {
+ WriteProperty(writer, "enum", resource.ApiVersions);
+ });
+
+ WriteProperty(writer, "properties", () =>
+ {
+ WriteObjectOrExpression(writer, () =>
+ {
+ WriteProperty(writer, "type", "object");
+ WriteProperty(writer, "properties", () =>
+ {
+ foreach (ResourceProperty property in resource.Properties)
+ {
+ WriteResourceProperty(writer, property);
+ }
+ });
+ WriteProperty(writer, "required", resource.RequiredPropertyNames);
+ });
+ });
+ });
+ WriteProperty(writer, "required", new string[]
+ {
+ "type",
+ "apiVersion",
+ "properties",
+ "location"
+ });
+ WriteProperty(writer, "description", resource.Description);
+ });
}
- private static IEnumerable GetResourceFullTypes(ServiceClient serviceClient)
+ private static void WriteResourceProperty(JsonTextWriter writer, ResourceProperty resourceProperty)
{
- IEnumerable resourceMethodUrisAfterPrefix = GetResourceMethodUrisAfterPrefix(serviceClient);
- return resourceMethodUrisAfterPrefix.Select(rmuap =>
+ WriteProperty(writer, resourceProperty.Name, () =>
{
- int forwardSlashAfterProvider = rmuap.IndexOf('/');
- int forwardSlashAfterType = rmuap.IndexOf('/', forwardSlashAfterProvider + 1);
- int startIndex = forwardSlashAfterProvider + 1;
- if (forwardSlashAfterType == -1)
+ WriteObjectOrExpression(writer, () =>
{
- return rmuap;
- }
- else
- {
- return rmuap.Substring(0, forwardSlashAfterType);
- }
- }).Distinct();
+ if (resourceProperty.Type != null)
+ {
+ WriteProperty(writer, "type", resourceProperty.Type);
+ }
+
+ if (resourceProperty.AllowedValues != null)
+ {
+ WriteProperty(writer, "allowedValues", resourceProperty.AllowedValues);
+ }
+ });
+ WriteProperty(writer, "description", resourceProperty.Description);
+ });
}
private static void WriteObject(JsonTextWriter writer, Action writeObjectContents)
@@ -162,19 +170,45 @@ private static void WriteObject(JsonTextWriter writer, Action writeObjectContent
writer.WriteEndObject();
}
+ private static void WriteExpressionReference(JsonTextWriter writer)
+ {
+ WriteObject(writer, () =>
+ {
+ WriteProperty(writer, "$ref", "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression");
+ });
+ }
+
+ private static void WriteObjectOrExpression(JsonTextWriter writer, Action writeObjectContents)
+ {
+ writer.WritePropertyName("oneOf");
+ writer.WriteStartArray();
+
+ WriteObject(writer, writeObjectContents);
+
+ WriteExpressionReference(writer);
+
+ writer.WriteEndArray();
+ }
+
private static void WriteProperty(JsonTextWriter writer, string propertyName, string propertyValue)
{
writer.WritePropertyName(propertyName);
writer.WriteValue(propertyValue);
}
+ private static void WriteProperty(JsonTextWriter writer, string propertyName, int 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)
+ private static void WriteProperty(JsonTextWriter writer, string propertyName, IEnumerable writeArrayContents)
{
writer.WritePropertyName(propertyName);
writer.WriteStartArray();
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/Resource.cs b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/Resource.cs
new file mode 100644
index 0000000000..fc1a67175c
--- /dev/null
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/Resource.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Rest.Generator.AzureResourceSchema
+{
+ public class Resource
+ {
+ private readonly string name;
+ private readonly string type;
+ private readonly string[] apiVersions;
+ private readonly IEnumerable properties;
+ private readonly string description;
+
+ public Resource(string name, string type, string[] apiVersions, IEnumerable properties, string description)
+ {
+ this.name = name;
+ this.type = type;
+ this.apiVersions = apiVersions;
+ this.properties = properties;
+ this.description = description;
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public string Type
+ {
+ get { return type; }
+ }
+
+ public string[] ApiVersions
+ {
+ get { return apiVersions; }
+ }
+
+ public IEnumerable Properties
+ {
+ get { return properties; }
+ }
+
+ public string[] RequiredPropertyNames
+ {
+ get { return Properties.Where(property => property.IsRequired).Select(property => property.Name).ToArray(); }
+ }
+
+ public string Description
+ {
+ get { return description; }
+ }
+ }
+}
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/ResourceProperty.cs b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/ResourceProperty.cs
new file mode 100644
index 0000000000..ecb0c10a6b
--- /dev/null
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/ResourceProperty.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+namespace Microsoft.Rest.Generator.AzureResourceSchema
+{
+ public class ResourceProperty
+ {
+ private readonly string name;
+ private readonly bool isRequired;
+ private readonly string type;
+ private readonly string[] allowedValues;
+ private readonly string description;
+
+ public ResourceProperty(string name, bool isRequired = false, string type = null, string[] allowedValues = null, string description = null)
+ {
+ this.name = name;
+ this.isRequired = isRequired;
+ this.type = type;
+ this.allowedValues = allowedValues;
+ this.description = description;
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public bool IsRequired
+ {
+ get { return isRequired; }
+ }
+
+ public string Type
+ {
+ get { return type; }
+ }
+
+ public string[] AllowedValues
+ {
+ get { return allowedValues; }
+ }
+
+ public string Description
+ {
+ get { return description; }
+ }
+ }
+}
diff --git a/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/Schema.cs b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/Schema.cs
new file mode 100644
index 0000000000..be3e1d0600
--- /dev/null
+++ b/AutoRest/Generators/AzureResourceSchema/AzureResourceSchema/Schema.cs
@@ -0,0 +1,170 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+using Microsoft.Rest.Generator.ClientModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Rest.Generator.AzureResourceSchema
+{
+ public class Schema
+ {
+ private const string resourceMethodPrefix = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/";
+
+ private readonly string id;
+ private readonly string title;
+ private readonly string description;
+ private readonly IEnumerable resources;
+
+ private Schema(string id, string title, string description, IEnumerable resources)
+ {
+ this.id = id;
+ this.title = title;
+ this.description = description;
+ this.resources = resources;
+ }
+
+ public string Id
+ {
+ get { return id; }
+ }
+
+ public string SchemaUri
+ {
+ get { return "http://json-schema.org/draft-04/schema#"; }
+ }
+
+ public string Title
+ {
+ get { return title; }
+ }
+
+ public string Description
+ {
+ get { return description; }
+ }
+
+ public IEnumerable Resources
+ {
+ get { return resources; }
+ }
+
+ public static Schema Parse(ServiceClient serviceClient)
+ {
+ string resourceProvider = GetResourceProvider(serviceClient);
+ string apiVersion = serviceClient.ApiVersion;
+
+ string id = String.Format("http://schema.management.azure.com/schemas/{0}/{1}.json#", apiVersion, resourceProvider);
+
+ string title = resourceProvider;
+
+ string description = resourceProvider.Replace('.', ' ') + " Resource Types";
+
+ List resources = new List();
+ foreach (Method resourceMethod in GetResourceMethods(serviceClient))
+ {
+ // Azure "create resource" methods are always PUTs.
+ if (resourceMethod.HttpMethod == HttpMethod.Put)
+ {
+ string resourceName = GetResourceName(resourceMethod);
+ string resourceType = GetResourceType(resourceMethod);
+ string[] apiVersions = new string[] { apiVersion };
+ List resourceProperties = new List();
+ string resourceDescription = resourceType;
+
+ CompositeType body = resourceMethod.Body.Type as CompositeType;
+ if (body != null)
+ {
+ CompositeType bodyProperties = body.Properties.Where(p => p.Name == "properties").Single().Type as CompositeType;
+ if (bodyProperties != null)
+ {
+ foreach (Property property in bodyProperties.Properties)
+ {
+ string propertyName = property.Name;
+ bool propertyIsRequired = property.IsRequired;
+ string propertyType = null;
+ string[] allowedValues = null;
+ string propertyDescription = String.Format("{0}: {1}", resourceType, property.Documentation);
+
+ if(property.Type is EnumType)
+ {
+ propertyType = "string";
+
+ EnumType propertyEnumType = property.Type as EnumType;
+ allowedValues = new string[propertyEnumType.Values.Count];
+ for (int i = 0; i < propertyEnumType.Values.Count; ++i)
+ {
+ allowedValues[i] = propertyEnumType.Values[i].Name;
+ }
+ }
+
+ resourceProperties.Add(new ResourceProperty(propertyName, propertyIsRequired, propertyType, allowedValues, propertyDescription));
+ }
+ }
+ }
+
+ resources.Add(new Resource(resourceName, resourceType, apiVersions, resourceProperties, resourceDescription));
+ }
+ }
+
+ return new Schema(id, title, description, resources);
+ }
+
+ private static IEnumerable GetResourceMethods(ServiceClient serviceClient)
+ {
+ return serviceClient.Methods.Where(method => method.Url.StartsWith(resourceMethodPrefix));
+ }
+
+ private static string GetResourceProvider(ServiceClient serviceClient)
+ {
+ return GetResourceMethods(serviceClient).Select(GetResourceProvider).Distinct().Single();
+ }
+
+ private static string GetResourceProvider(Method resourceMethod)
+ {
+ string afterPrefix = resourceMethod.Url.Substring(resourceMethodPrefix.Length);
+ int firstForwardSlashAfterPrefix = afterPrefix.IndexOf('/');
+ return afterPrefix.Substring(0, firstForwardSlashAfterPrefix);
+ }
+
+ private static string GetResourceName(Method resourceMethod)
+ {
+ string afterPrefix = resourceMethod.Url.Substring(resourceMethodPrefix.Length);
+ int forwardSlashIndexAfterProvider = afterPrefix.IndexOf('/');
+ int resourceNameStartIndex = forwardSlashIndexAfterProvider + 1;
+ int forwardSlashIndexAfterResourceName = afterPrefix.IndexOf('/', resourceNameStartIndex);
+
+ string result;
+ if(forwardSlashIndexAfterResourceName == -1)
+ {
+ result = afterPrefix.Substring(resourceNameStartIndex);
+ }
+ else
+ {
+ result = afterPrefix.Substring(resourceNameStartIndex, forwardSlashIndexAfterResourceName - resourceNameStartIndex);
+ }
+
+ return result;
+ }
+
+ private static string GetResourceType(Method resourceMethod)
+ {
+ string afterPrefix = resourceMethod.Url.Substring(resourceMethodPrefix.Length);
+ int forwardSlashIndexAfterProvider = afterPrefix.IndexOf('/');
+ int forwardSlashIndexAfterResourceName = afterPrefix.IndexOf('/', forwardSlashIndexAfterProvider + 1);
+
+ string result;
+ if(forwardSlashIndexAfterResourceName == -1)
+ {
+ result = afterPrefix;
+ }
+ else
+ {
+ result = afterPrefix.Substring(0, forwardSlashIndexAfterResourceName);
+ }
+
+ return result;
+ }
+ }
+}