-
Notifications
You must be signed in to change notification settings - Fork 756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add library support for local deployments #14237
Conversation
Test this change out locally with the following install scripts (Action run 9409014946) VSCode
Azure CLI
|
ce644d7
to
5f01f51
Compare
e52e251
to
9023c38
Compare
9023c38
to
2fa4456
Compare
443f0ea
to
bc33931
Compare
@@ -48,7 +48,7 @@ public static GrpcChannel CreateChannel(string socketPath) | |||
}; | |||
|
|||
// The URL is not used, but it must be a valid URI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this URL needed for then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's parsed initially by the GrpcChannel
API (which throws if it's invalid), but the actual socket connection logic is overridden by setting the HttpHandler
} | ||
} | ||
|
||
private async Task SaveDeployment(DeploymentPlan deploymentPlan) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify, SaveDeployment means that the deployment is kept track of locally, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm using in-memory data providers, so when we "save" an entity, we are replacing it in memory. This is only available while the process is running - it is not persisted afterwards.
|
||
public string[] PreviewFunctionalityExternalPermittedTenants { get; set; } = new string[] { }; | ||
|
||
public string[] PreviewFunctionalityPublicFeatures { get; set; } = new string[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm probably a little confused but where does this get checked compared to the ServiceDirectory.json? Or is it not at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not so relevant for this particular feature, but I'm forced to define a value for it.
|
||
public static async Task<Result> Deploy(LocalExtensibilityHandler extensibilityHandler, string templateString, string parametersString, CancellationToken cancellationToken) | ||
{ | ||
var services = new ServiceCollection() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this is a short-cut, or de we want to register and build the service provider every time .Deploy is invoked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a short-cut for now - https://msazure.visualstudio.com/One/_workitems/edit/28299061 would be the proper implementation for it.
} | ||
finally | ||
{ | ||
await dispatcher.StopAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does distacher.Start()
happens?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question, I think it must be happening inside the deployment engine. It's important to stop regardless, so that we don't leak jobs when running in the language server.
return new( | ||
deploymentEngine.CreateDeploymentDefinition(entity, requestContext.ApiVersion), | ||
operationEntities | ||
.Where(operation => operation.TargetResource is not null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When is TargetResource
null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deployment last job creates a single operation for "processing outputs" - this filters it down to just resource operations.
{ | ||
await Task.Delay(500, cancellationToken); | ||
|
||
entity = await dataProvider.FindDeployment(context.SubscriptionId, context.ResourceGroupName, context.DeploymentName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is interesting, in ARM, we go off the async header and poll for the status, here we don't have such option, something we could explore at some point is standing up a local deployments server, so we can reuse the same deploymentsWorkflow rather than implementing a local deployment engine.
Also, a TODO to add here is to gracefully handle an exception thrown by volatile datastore also to not loop indefinitely or until the cancellation is requested
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to avoid polling here - it's a consequence of low visibility into ResourceStack's job processing internals. I've cut the polling down to every 20ms to make it more responsive as it should be very low-cost.
var parameters = new JObject { | ||
["$schema"] = "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", | ||
["contentVersion"] = "1.0.0.0", | ||
["parameters"] = request.Resource.Properties["parameters"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO, account for parametersLink and templateLink?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good callout - something to think through.
{ | ||
switch (request.Resource.Type) | ||
{ | ||
case "Microsoft.Resources/deployments": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is Az extensibility provider, can this type be any azure resource type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not currently - it's out of scope for the first phase.
|
||
private async Task<ExtensibilityOperationResponse> CallProvider(string method, IExtensibilityProvider provider, ExtensibilityOperationRequest request, CancellationToken cancellationToken) | ||
{ | ||
return method switch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: move to enum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good callout!
Add
Bicep.Local.Deploy
library containing "local deployment" logic.The full spec is available here - unfortunately only available to Microsoft employees currently.
Microsoft Reviewers: Open in CodeFlow