-
Notifications
You must be signed in to change notification settings - Fork 773
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add resource types in outputs and parameters
Fixes: #2246 This change implements functionality for declaring strongly type parameters and outputs using resource types. Example: ``` param storage resource 'Microsoft.Storage/storageAccounts@2020-01-01' ``` This declares a parameter that can be interacted with as-if it were an 'existing' resource type declaration of the provided type. In addition you can do the same with outputs: ``` output out resource 'Microsoft.Storage/storageAccounts@2020-01-01' = foo ``` or using type inference (outputs): ``` output out resource = foo ``` These features together allow you to pass resources across module boundaries, and as command line parameters (using the resource ID). --- This PR implements #2246 with a few caveats that I discussed offline with one of the maintainers. 1. It does not include the 'any resource type' that's outlined in the proposal. It's not clear how that part of the proposal will work in the future with extensibility. 2. It does not support extensibility resources currently. To do this we need to define the semantics of how an extensibility resource can be serialized (what's the equivalent of `.id`). This is explicitly blocked in the first cut and can be added as extensibility is designed. 3. Parameter resources cannot be used with the `.parent` or `.scope` properties because it would allow you to bypass scope validation easily. The set of cases that we could actually provide validation for these use cases are really limited.
- Loading branch information
Showing
93 changed files
with
2,161 additions
and
539 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
using System.Diagnostics.CodeAnalysis; | ||
using Bicep.Core.Diagnostics; | ||
using Bicep.Core.IntegrationTests.Extensibility; | ||
using Bicep.Core.TypeSystem; | ||
using Bicep.Core.UnitTests; | ||
using Bicep.Core.UnitTests.Assertions; | ||
using Bicep.Core.UnitTests.Utils; | ||
using FluentAssertions; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using Newtonsoft.Json.Linq; | ||
|
||
namespace Bicep.Core.IntegrationTests | ||
{ | ||
[TestClass] | ||
public class OutputsTests | ||
{ | ||
[NotNull] | ||
public TestContext? TestContext { get; set; } | ||
|
||
private CompilationHelper.CompilationHelperContext GetExtensibilityCompilationContext() | ||
{ | ||
var features = BicepTestConstants.CreateFeaturesProvider(TestContext, importsEnabled: true); | ||
var resourceTypeLoader = BicepTestConstants.AzResourceTypeLoader; | ||
var namespaceProvider = new ExtensibilityNamespaceProvider(resourceTypeLoader, features); | ||
|
||
return new( | ||
AzResourceTypeLoader: resourceTypeLoader, | ||
Features: features, | ||
NamespaceProvider: namespaceProvider); | ||
} | ||
|
||
[TestMethod] | ||
public void Output_can_have_inferred_resource_type() | ||
{ | ||
var result = CompilationHelper.Compile(@" | ||
resource resource 'Microsoft.Storage/storageAccounts@2019-06-01' = { | ||
name: 'test' | ||
location: 'eastus' | ||
kind: 'StorageV2' | ||
sku: { | ||
name: 'Standard_LRS' | ||
} | ||
identity: { | ||
type: 'SystemAssigned' | ||
} | ||
properties:{ | ||
accessTier: 'Cool' | ||
} | ||
} | ||
output out resource = resource | ||
"); | ||
result.Should().NotHaveAnyDiagnostics(); | ||
|
||
var model = result.Compilation.GetEntrypointSemanticModel(); | ||
var @out = model.Root.OutputDeclarations.Should().ContainSingle().Subject; | ||
var typeInfo = model.GetTypeInfo(@out.DeclaringSyntax); | ||
typeInfo.Should().BeOfType<ResourceType>().Which.TypeReference.FormatName().Should().BeEquivalentTo("Microsoft.Storage/storageAccounts@2019-06-01"); | ||
|
||
result.Template.Should().HaveValueAtPath("$.outputs.out", new JObject() | ||
{ | ||
["type"] = "string", | ||
["value"] = "[resourceId('Microsoft.Storage/storageAccounts', 'test')]", | ||
["metadata"] = new JObject() | ||
{ | ||
["resourceType"] = new JValue("Microsoft.Storage/storageAccounts@2019-06-01"), | ||
}, | ||
}); | ||
} | ||
|
||
[TestMethod] | ||
public void Output_can_have_specified_resource_type() | ||
{ | ||
var result = CompilationHelper.Compile(@" | ||
resource resource 'Microsoft.Storage/storageAccounts@2019-06-01' = { | ||
name: 'test' | ||
location: 'eastus' | ||
kind: 'StorageV2' | ||
sku: { | ||
name: 'Standard_LRS' | ||
} | ||
identity: { | ||
type: 'SystemAssigned' | ||
} | ||
properties:{ | ||
accessTier: 'Cool' | ||
} | ||
} | ||
output out resource 'Microsoft.Storage/storageAccounts@2019-06-01' = resource | ||
"); | ||
result.Should().NotHaveAnyDiagnostics(); | ||
|
||
var model = result.Compilation.GetEntrypointSemanticModel(); | ||
var @out = model.Root.OutputDeclarations.Should().ContainSingle().Subject; | ||
var typeInfo = model.GetTypeInfo(@out.DeclaringSyntax); | ||
typeInfo.Should().BeOfType<ResourceType>().Which.TypeReference.FormatName().Should().BeEquivalentTo("Microsoft.Storage/storageAccounts@2019-06-01"); | ||
|
||
result.Template.Should().HaveValueAtPath("$.outputs.out", new JObject() | ||
{ | ||
["type"] = "string", | ||
["value"] = "[resourceId('Microsoft.Storage/storageAccounts', 'test')]", | ||
["metadata"] = new JObject() | ||
{ | ||
["resourceType"] = new JValue("Microsoft.Storage/storageAccounts@2019-06-01"), | ||
}, | ||
}); | ||
} | ||
|
||
[TestMethod] | ||
public void Output_cannot_use_extensibility_resource_type() | ||
{ | ||
var result = CompilationHelper.Compile(GetExtensibilityCompilationContext(), @" | ||
import stg from storage { | ||
connectionString: 'asdf' | ||
} | ||
resource container 'AzureStorage/containers@2020-01-01' = { | ||
name: 'myblob' | ||
} | ||
output out resource = container | ||
"); | ||
result.Should().HaveDiagnostics(new [] | ||
{ | ||
("BCP225", DiagnosticLevel.Error, "The type \"AzureStorage/containers@2020-01-01\" cannot be used as an output type."), | ||
}); | ||
} | ||
} | ||
} |
Oops, something went wrong.