-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Enabling custom script extension support for VMSS deployment #4645
Changes from 1 commit
124079d
7a2a392
f3f630f
cb9b451
2fb49fa
f1e5702
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,10 +12,11 @@ export default class VirtualMachineScaleSet { | |
this.taskParameters = taskParameters; | ||
} | ||
|
||
public execute(): Promise<void> { | ||
public async execute(): Promise<void> { | ||
var client = new armCompute.ComputeManagementClient(this.taskParameters.credentials, this.taskParameters.subscriptionId); | ||
return new Promise<void>((resolve, reject) => { | ||
this._getResourceGroupForVmss(client,resolve, reject, (error, result, request, response) => { | ||
return new Promise<void>(async (resolve, reject) => { | ||
try { | ||
var result = await this._getResourceGroupForVmss(client); | ||
var resourceGroupName: string = result.resourceGroupName; | ||
var osType: string = result.osType; | ||
if(!resourceGroupName) { | ||
|
@@ -24,135 +25,143 @@ export default class VirtualMachineScaleSet { | |
|
||
switch (this.taskParameters.action) { | ||
case "UpdateImage": | ||
var extensionMetadata: azureModel.VMExtensionMetadata = null; | ||
var customScriptExtension: azureModel.VMExtension = null; | ||
if(!!this.taskParameters.customScriptUrl) { | ||
extensionMetadata = this._getCustomScriptExtensionMetadata(osType); | ||
customScriptExtension = { | ||
name: "CustomScriptExtension" + Date.now().toString(), | ||
properties: { | ||
type: extensionMetadata.type, | ||
publisher: extensionMetadata.publisher, | ||
typeHandlerVersion: extensionMetadata.typeHandlerVersion, | ||
autoUpgradeMinorVersion: true, | ||
settings: { | ||
"fileUris": [ this.taskParameters.customScriptUrl ] | ||
}, | ||
protectedSettings: { | ||
"commandToExecute": this.taskParameters.customScriptCommand | ||
var extensionMetadata: azureModel.VMExtensionMetadata = null; | ||
var customScriptExtension: azureModel.VMExtension = null; | ||
if(!!this.taskParameters.customScriptUrl) { | ||
extensionMetadata = this._getCustomScriptExtensionMetadata(osType); | ||
customScriptExtension = { | ||
name: "CustomScriptExtension" + Date.now().toString(), | ||
properties: { | ||
type: extensionMetadata.type, | ||
publisher: extensionMetadata.publisher, | ||
typeHandlerVersion: extensionMetadata.typeHandlerVersion, | ||
autoUpgradeMinorVersion: true, | ||
settings: { | ||
"fileUris": [ this.taskParameters.customScriptUrl ] | ||
}, | ||
protectedSettings: { | ||
"commandToExecute": this.taskParameters.customScriptCommand | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
|
||
this._getExistingCustomScriptExtension(client, resourceGroupName, customScriptExtension, (error, matchingExtension, request, response) => { | ||
var matchingExtension = await this._getExistingCustomScriptExtension(client, resourceGroupName, customScriptExtension); | ||
// if extension already exists, remove it | ||
if(!!matchingExtension) { | ||
this._deleteAndInstallCustomScriptExtension(client, resourceGroupName, matchingExtension, customScriptExtension, resolve, reject, (error, matchingExtension, request, response) => { | ||
this._updateImageInternal(client, resourceGroupName, resolve, reject); | ||
}); | ||
await this._deleteAndInstallCustomScriptExtension(client, resourceGroupName, matchingExtension, customScriptExtension); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: similarly consider if you need to merge this method now. Or you can delete if a matching extension is found. Install extension always. And then update image. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
await this._updateImageInternal(client, resourceGroupName); | ||
} else { | ||
this._installCustomScripExtension(client, resourceGroupName, customScriptExtension, resolve, reject, (error, result, request, response) => { | ||
this._updateImageInternal(client, resourceGroupName, resolve, reject); | ||
}); | ||
await this._installCustomScripExtension(client, resourceGroupName, customScriptExtension); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For my knowledge, is this the right way to update image (to do it in two steps). Would it lead to smooth upgrade; I thought earlier logic of merged update was better for upgrade; i.e. would it lead to zero downtime? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there were few reasons why I did like this:
|
||
await this._updateImageInternal(client, resourceGroupName); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Consider not repeating it now. Since this is all await. You can call it once (outside of all conditions) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
}); | ||
} else { | ||
this._updateImageInternal(client, resourceGroupName, resolve, reject); | ||
} | ||
|
||
break; | ||
} else { | ||
await this._updateImageInternal(client, resourceGroupName); | ||
} | ||
break; | ||
} | ||
}); | ||
} catch(error) { | ||
reject(error); | ||
} | ||
}); | ||
} | ||
|
||
private _getResourceGroupForVmss(client, resolve, reject, callback): void { | ||
client.virtualMachineScaleSets.list(null, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("VMSSListFetchFailed", this.taskParameters.vmssName, utils.getError(error))); | ||
} | ||
private _getResourceGroupForVmss(client): Promise<any> { | ||
return new Promise<any>((resolve, reject) => { | ||
client.virtualMachineScaleSets.list(null, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("VMSSListFetchFailed", this.taskParameters.vmssName, utils.getError(error))); | ||
} | ||
|
||
var vmssList: azureModel.VMSS[] = result; | ||
if (vmssList.length == 0) { | ||
console.log(tl.loc("NoVMSSFound", this.taskParameters.vmssName)); | ||
return resolve(); | ||
} | ||
var vmssList: azureModel.VMSS[] = result; | ||
if (vmssList.length == 0) { | ||
console.log(tl.loc("NoVMSSFound", this.taskParameters.vmssName)); | ||
return resolve(); | ||
} | ||
|
||
var resourceGroupName: string; | ||
var osType: string; | ||
for (var i = 0; i < vmssList.length; i++) { | ||
if(vmssList[i].name.toUpperCase() === this.taskParameters.vmssName.toUpperCase()) | ||
{ | ||
resourceGroupName = utils.getResourceGroupNameFromUri(vmssList[i].id); | ||
osType = vmssList[i].properties.virtualMachineProfile.storageProfile.osDisk.osType; | ||
break; | ||
var resourceGroupName: string; | ||
var osType: string; | ||
for (var i = 0; i < vmssList.length; i++) { | ||
if(vmssList[i].name.toUpperCase() === this.taskParameters.vmssName.toUpperCase()) | ||
{ | ||
resourceGroupName = utils.getResourceGroupNameFromUri(vmssList[i].id); | ||
osType = vmssList[i].properties.virtualMachineProfile.storageProfile.osDisk.osType; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
callback(null, { resourceGroupName: resourceGroupName, osType: osType }); | ||
return resolve({ resourceGroupName: resourceGroupName, osType: osType }); | ||
}); | ||
}); | ||
} | ||
|
||
private _getExistingCustomScriptExtension(client, resourceGroupName, customScriptExtension, callback): void { | ||
client.virtualMachineExtensions.list(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, null, (error, result, request, response) => { | ||
if (error) { | ||
// Just log warning, do not fail | ||
tl.warning(tl.loc("GetVMSSExtensionsListFailed", this.taskParameters.vmssName, utils.getError(error))); | ||
} | ||
|
||
var extensions: azureModel.VMExtension[] = result || []; | ||
var matchingExtension: azureModel.VMExtension = null; | ||
extensions.forEach((extension: azureModel.VMExtension) => { | ||
if(extension.properties.type === customScriptExtension.properties.type && | ||
extension.properties.publisher === customScriptExtension.properties.publisher) { | ||
matchingExtension = extension; | ||
return; | ||
private _getExistingCustomScriptExtension(client, resourceGroupName, customScriptExtension): Promise<azureModel.VMExtension> { | ||
return new Promise<azureModel.VMExtension>((resolve, reject) => { | ||
client.virtualMachineExtensions.list(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, null, (error, result, request, response) => { | ||
if (error) { | ||
// Just log warning, do not fail | ||
tl.warning(tl.loc("GetVMSSExtensionsListFailed", this.taskParameters.vmssName, utils.getError(error))); | ||
} | ||
}); | ||
|
||
callback(null, matchingExtension); | ||
var extensions: azureModel.VMExtension[] = result || []; | ||
var matchingExtension: azureModel.VMExtension = null; | ||
extensions.forEach((extension: azureModel.VMExtension) => { | ||
if(extension.properties.type === customScriptExtension.properties.type && | ||
extension.properties.publisher === customScriptExtension.properties.publisher) { | ||
matchingExtension = extension; | ||
return; | ||
} | ||
}); | ||
|
||
return resolve(matchingExtension); | ||
}); | ||
}); | ||
} | ||
|
||
private _deleteAndInstallCustomScriptExtension(client, resourceGroupName, oldExtension, newExtension, resolve, reject, callback): void { | ||
console.log(tl.loc("RemovingCustomScriptExtension", oldExtension.name)); | ||
client.virtualMachineExtensions.deleteMethod(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, oldExtension.name, (error, result, request, response) => { | ||
if (error) { | ||
// Just log warning, do not fail | ||
tl.warning(tl.loc("RemoveVMSSExtensionsFailed", oldExtension.name, utils.getError(error))); | ||
} else { | ||
console.log(tl.loc("CustomScriptExtensionRemoved", oldExtension.name)); | ||
} | ||
|
||
client.virtualMachineExtensions.createOrUpdate(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, newExtension.name, newExtension, (error, result, request, response) => { | ||
private _deleteAndInstallCustomScriptExtension(client, resourceGroupName, oldExtension, newExtension): Promise<void> { | ||
return new Promise<void>((resolve, reject) => { | ||
console.log(tl.loc("RemovingCustomScriptExtension", oldExtension.name)); | ||
client.virtualMachineExtensions.deleteMethod(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, oldExtension.name, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("SettingVMExtensionFailed", utils.getError(error))); | ||
// Just log warning, do not fail | ||
tl.warning(tl.loc("RemoveVMSSExtensionsFailed", oldExtension.name, utils.getError(error))); | ||
} else { | ||
console.log(tl.loc("CustomScriptExtensionRemoved", oldExtension.name)); | ||
} | ||
|
||
console.log(tl.loc("CustomScriptExtensionInstalled", newExtension.name)); | ||
callback(null, null); | ||
client.virtualMachineExtensions.createOrUpdate(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, newExtension.name, newExtension, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("SettingVMExtensionFailed", utils.getError(error))); | ||
} | ||
|
||
console.log(tl.loc("CustomScriptExtensionInstalled", newExtension.name)); | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
private _installCustomScripExtension(client, resourceGroupName, customScriptExtension, resolve, reject, callback): void { | ||
client.virtualMachineExtensions.createOrUpdate(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, customScriptExtension.name, customScriptExtension, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("SettingVMExtensionFailed", utils.getError(error))); | ||
} | ||
private _installCustomScripExtension(client, resourceGroupName, customScriptExtension): Promise<void> { | ||
return new Promise<void>((resolve, reject) => { | ||
client.virtualMachineExtensions.createOrUpdate(resourceGroupName, this.taskParameters.vmssName, azureModel.ComputeResourceType.VirtualMachineScaleSet, customScriptExtension.name, customScriptExtension, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("SettingVMExtensionFailed", utils.getError(error))); | ||
} | ||
|
||
console.log(tl.loc("CustomScriptExtensionInstalled", customScriptExtension.name)); | ||
callback(null, null); | ||
console.log(tl.loc("CustomScriptExtensionInstalled", customScriptExtension.name)); | ||
return resolve(); | ||
}); | ||
}); | ||
} | ||
|
||
private _updateImageInternal(client, resourceGroupName, resolve, reject) { | ||
client.virtualMachineScaleSets.updateImage(resourceGroupName, this.taskParameters.vmssName, this.taskParameters.imageUrl, null, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("VMSSImageUpdateFailed", utils.getError(error))); | ||
} | ||
console.log(tl.loc("UpdatedVMSSImage")); | ||
return resolve(); | ||
private _updateImageInternal(client, resourceGroupName): Promise<void> { | ||
return new Promise<void>((resolve, reject) => { | ||
client.virtualMachineScaleSets.updateImage(resourceGroupName, this.taskParameters.vmssName, this.taskParameters.imageUrl, null, (error, result, request, response) => { | ||
if (error) { | ||
return reject(tl.loc("VMSSImageUpdateFailed", utils.getError(error))); | ||
} | ||
console.log(tl.loc("UpdatedVMSSImage")); | ||
return resolve(); | ||
}); | ||
}); | ||
} | ||
|
||
|
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.
you can remove creating and returning this promise as well since your method is async
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.
you are right. infact removed try-catch also