-
Notifications
You must be signed in to change notification settings - Fork 0
adding ssh support for both linux and windows #3
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
Changes from all commits
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 |
|---|---|---|
|
|
@@ -27,7 +27,9 @@ function getVersion(callback) { | |
| */ | ||
| function getLimits(callback) { | ||
| return errs.handle( | ||
| errs.create({ message: 'Azure\'s API is not rate limited' }), | ||
| errs.create({ | ||
| message: 'Azure\'s API is not rate limited' | ||
| }), | ||
| callback | ||
| ); | ||
| } | ||
|
|
@@ -48,9 +50,9 @@ function getServers(callback) { | |
|
|
||
| var client = new ComputeManagementClient(self.azure.credentials, self.config.subscriptionId); | ||
| client.virtualMachines.list(self.config.resourceGroup, function (err, results) { | ||
| return err | ||
| ? callback(err) | ||
| : callback(null, results.map(function (res) { | ||
| return err ? | ||
| callback(err) : | ||
| callback(null, results.map(function (res) { | ||
| return new self.models.Server(self, res); | ||
| })); | ||
| }); | ||
|
|
@@ -63,7 +65,7 @@ function getServers(callback) { | |
| * @param {Function} callback cb(err, serverId). | ||
| */ | ||
| function getServer(server, callback) { | ||
| var self = this; | ||
| var self = this; | ||
| var serverId = server instanceof self.models.Server ? server.name : server; | ||
|
|
||
| self.login(function (err) { | ||
|
|
@@ -73,37 +75,39 @@ function getServer(server, callback) { | |
| } | ||
|
|
||
| var client = new ComputeManagementClient(self.azure.credentials, self.config.subscriptionId); | ||
|
|
||
| // This will ensure returning of instances running status | ||
| var options = { expand: 'instanceView' }; | ||
| var options = { | ||
| expand: 'instanceView' | ||
| }; | ||
| client.virtualMachines.get(self.config.resourceGroup, serverId, options, function (err, result) { | ||
|
|
||
| if (err) { | ||
| return callback(err); | ||
| } | ||
|
|
||
| // Get public dns url | ||
| if (!result.networkProfile || | ||
| !result.networkProfile.networkInterfaces || | ||
| !result.networkProfile.networkInterfaces.length) { | ||
| if (!result.networkProfile || | ||
| !result.networkProfile.networkInterfaces || | ||
| !result.networkProfile.networkInterfaces.length) { | ||
| return callback(null, new self.models.Server(self, result)); | ||
| } | ||
|
|
||
| var networkInterfaceId = result.networkProfile.networkInterfaces[0].id; | ||
| var resourceClient = new resourceManagement.ResourceManagementClient(self.azure.credentials, self.config.subscriptionId); | ||
|
|
||
| resourceClient.resources.getById(networkInterfaceId, constants.DEFAULT_API_VERSION, function (err, networkInterface) { | ||
|
|
||
| if (err) { | ||
| return callback(err); | ||
| } | ||
|
|
||
| if (!networkInterface.properties.ipConfigurations || | ||
| !networkInterface.properties.ipConfigurations.length || | ||
| !networkInterface.properties.ipConfigurations[0] || | ||
| !networkInterface.properties.ipConfigurations[0].properties || | ||
| !networkInterface.properties.ipConfigurations[0].properties.publicIPAddress || | ||
| !networkInterface.properties.ipConfigurations[0].properties.publicIPAddress.id) { | ||
| !networkInterface.properties.ipConfigurations.length || | ||
| !networkInterface.properties.ipConfigurations[0] || | ||
| !networkInterface.properties.ipConfigurations[0].properties || | ||
| !networkInterface.properties.ipConfigurations[0].properties.publicIPAddress || | ||
| !networkInterface.properties.ipConfigurations[0].properties.publicIPAddress.id) { | ||
| return callback(null, new self.models.Server(self, result)); | ||
| } | ||
|
|
||
|
|
@@ -143,21 +147,27 @@ function createServer(options, callback) { | |
|
|
||
| if (!options.name || !options.username || !options.password) { | ||
| return errs.handle( | ||
| errs.create({ message: 'Please provide a name for the vm, as well as the username and password for login' }), | ||
| errs.create({ | ||
| message: 'Please provide a name for the vm, as well as the username and password for login' | ||
| }), | ||
| callback | ||
| ); | ||
| } | ||
|
|
||
| if (!options.flavor) { | ||
| return errs.handle( | ||
| errs.create({ message: 'When creating an azure server a flavor or an image need to be supplied' }), | ||
| errs.create({ | ||
| message: 'When creating an azure server a flavor or an image need to be supplied' | ||
| }), | ||
| callback | ||
| ); | ||
| } | ||
|
|
||
| var adjustVMTemplate = function (template) { | ||
|
|
||
| var vmIndex = _.findIndex(template.resources, { 'type': 'Microsoft.Compute/virtualMachines' }); | ||
| var vmIndex = _.findIndex(template.resources, { | ||
| 'type': 'Microsoft.Compute/virtualMachines' | ||
| }); | ||
|
|
||
| // Adding additional data disks | ||
| if (options.storageDataDiskNames && options.storageDataDiskNames.length) { | ||
|
|
@@ -174,11 +184,11 @@ function createServer(options, callback) { | |
| }); | ||
| } | ||
|
|
||
| // If this is a windows machine, add an extension that enables remote connection via WinRM | ||
| // If this is a windows machine, add an extension that enables ssh connection via Win32-OpenSSH | ||
| if (options.osType === 'Windows') { | ||
| template.resources[vmIndex].resources = [{ | ||
| 'type': 'Microsoft.Compute/virtualMachines/extensions', | ||
| 'name': '[concat(variables(\'vmName\'),\'/WinRMCustomScriptExtension\')]', | ||
| 'name': '[concat(variables(\'vmName\'),\'/Win32sshExtension\')]', | ||
| 'apiVersion': constants.DEFAULT_API_VERSION, | ||
| 'location': '[resourceGroup().location]', | ||
| 'dependsOn': [ | ||
|
|
@@ -187,15 +197,30 @@ function createServer(options, callback) { | |
| 'properties': { | ||
| 'publisher': 'Microsoft.Compute', | ||
| 'type': 'CustomScriptExtension', | ||
| 'typeHandlerVersion': '1.4', | ||
| 'typeHandlerVersion': '1.8', | ||
| 'settings': { | ||
| 'fileUris': [ | ||
| 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vm-winrm-windows/ConfigureWinRM.ps1', | ||
| 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vm-winrm-windows/makecert.exe', | ||
| 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vm-winrm-windows/winrmconf.cmd' | ||
| ], | ||
| 'commandToExecute': '[concat(\'powershell -ExecutionPolicy Unrestricted -file ConfigureWinRM.ps1 \',variables(\'hostDNSNameScriptArgument\'))]' | ||
| } | ||
| 'fileUris': ["https://raw.githubusercontent.com/CatalystCode/pkgcloud/master/lib/pkgcloud/azure-v2/scripts/ssh.ps1"], | ||
| 'commandToExecute': `powershell -File ssh.ps1 ${hostname}\\${options.username} ${options.password}` | ||
| }, | ||
| } | ||
| }]; | ||
| } else { // linux - make sure the new user is in sudoers - so he can sudo with no password | ||
| template.resources[vmIndex].resources = [{ | ||
| 'type': 'Microsoft.Compute/virtualMachines/extensions', | ||
|
Collaborator
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. Why did you also add a linux extension? from what I remember ssh works by default on Linux machine
Collaborator
Author
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. It does work, but in none ubuntu linux by default the azure user is not a passwordless sudoer, it has to enter his password before sudoing - so this patch fixes that. |
||
| 'name': '[concat(variables(\'vmName\'),\'/LinuxSudoExtension\')]', | ||
| 'apiVersion': constants.DEFAULT_API_VERSION, | ||
| 'location': '[resourceGroup().location]', | ||
| 'dependsOn': [ | ||
| '[concat(\'Microsoft.Compute/virtualMachines/\', variables(\'vmName\'))]' | ||
| ], | ||
| 'properties': { | ||
| 'publisher': 'Microsoft.Compute', | ||
| 'type': 'CustomScriptForLinux', | ||
| 'typeHandlerVersion': '1.5', | ||
| 'settings': { | ||
| 'fileUris': ["https://raw.githubusercontent.com/CatalystCode/pkgcloud/master/lib/pkgcloud/azure-v2/scripts/sudo.sh"], | ||
| 'commandToExecute': 'bash sudo.sh ' + options.username | ||
| }, | ||
| } | ||
| }]; | ||
| } | ||
|
|
@@ -236,7 +261,7 @@ function destroyServer(server, options, callback) { | |
| var serverDetails; | ||
| var nicsIds; | ||
| var nicsDetails; | ||
|
|
||
| var vnets; | ||
| var publicIPs; | ||
|
|
||
|
|
@@ -255,7 +280,7 @@ function destroyServer(server, options, callback) { | |
| // Deleting the vm | ||
| resourceClient = new resourceManagement.ResourceManagementClient(self.azure.credentials, self.config.subscriptionId); | ||
| var client = new ComputeManagementClient(self.azure.credentials, self.config.subscriptionId); | ||
| client.virtualMachines.deleteMethod(self.config.resourceGroup, serverId, next); | ||
| client.virtualMachines.deleteMethod(self.config.resourceGroup, serverId, next); | ||
| } | ||
| ], function (err) { | ||
|
|
||
|
|
@@ -264,19 +289,19 @@ function destroyServer(server, options, callback) { | |
| } | ||
|
|
||
| if (!options.destroyNics && | ||
| !options.destroyPublicIP && | ||
| !options.destroyVnet && | ||
| !options.destroyStorage) { | ||
| !options.destroyPublicIP && | ||
| !options.destroyVnet && | ||
| !options.destroyStorage) { | ||
| return callback(); | ||
| } | ||
|
|
||
| async.waterfall([ | ||
| function (next) { | ||
| // Deleting the nics | ||
| nicsIds = serverDetails && | ||
| serverDetails.azure && | ||
| serverDetails.azure.networkProfile && | ||
| serverDetails.azure.networkProfile.networkInterfaces || []; | ||
| nicsIds = serverDetails && | ||
| serverDetails.azure && | ||
| serverDetails.azure.networkProfile && | ||
| serverDetails.azure.networkProfile.networkInterfaces || []; | ||
|
|
||
| // Go over all nics, get their details and go on to delete them | ||
| async.eachSeries(nicsIds, function (nic, cb) { | ||
|
|
@@ -329,7 +354,7 @@ function destroyServer(server, options, callback) { | |
| // Deleting public ips | ||
| async.eachSeries(publicIPs, function (publicIP, cb) { | ||
| resourceClient.resources.deleteById(publicIP, constants.MANAGEMENT_API_VERSION, cb); | ||
| }, next); | ||
| }, next); | ||
| }, | ||
| function (next) { | ||
|
|
||
|
|
@@ -340,20 +365,20 @@ function destroyServer(server, options, callback) { | |
| // Deleting vnets | ||
| async.eachSeries(vnets, function (vnet, cb) { | ||
| resourceClient.resources.deleteById(vnet, constants.MANAGEMENT_API_VERSION, cb); | ||
| }, next); | ||
| }, next); | ||
| }, | ||
| function (next) { | ||
| // Deleting storage account | ||
| if (!options.destroyStorage) { | ||
| return next(); | ||
| } | ||
|
|
||
| var storageUri = serverDetails && | ||
| serverDetails.azure && | ||
| serverDetails.azure.storageProfile && | ||
| serverDetails.azure.storageProfile.osDisk && | ||
| serverDetails.azure.storageProfile.osDisk.vhd && | ||
| serverDetails.azure.storageProfile.osDisk.vhd.uri || null; | ||
| var storageUri = serverDetails && | ||
| serverDetails.azure && | ||
| serverDetails.azure.storageProfile && | ||
| serverDetails.azure.storageProfile.osDisk && | ||
| serverDetails.azure.storageProfile.osDisk.vhd && | ||
| serverDetails.azure.storageProfile.osDisk.vhd.uri || null; | ||
|
|
||
| if (!storageUri || !storageUri.startsWith('https://')) { | ||
| return next(); | ||
|
|
@@ -364,17 +389,17 @@ function destroyServer(server, options, callback) { | |
|
|
||
| // Presuming the storage account is in the same resource group as the vm | ||
| resourceClient.resources.deleteMethod( | ||
| self.config.resourceGroup, | ||
| 'Microsoft.Storage', | ||
| 'storageAccounts', | ||
| storageName, | ||
| self.config.resourceGroup, | ||
| 'Microsoft.Storage', | ||
| 'storageAccounts', | ||
| storageName, | ||
| '', '2016-01-01', next); | ||
| } | ||
| ], function (error) { | ||
| callback(error, serverDetails); | ||
| }); | ||
| }); | ||
|
|
||
| } | ||
|
|
||
| /** | ||
|
|
@@ -394,9 +419,9 @@ function stopServer(server, callback) { | |
|
|
||
| var client = new ComputeManagementClient(self.azure.credentials, self.config.subscriptionId); | ||
| client.virtualMachines.powerOff(self.config.resourceGroup, serverId, function (err) { | ||
| return err | ||
| ? callback(err) | ||
| : callback(null, serverId); | ||
| return err ? | ||
| callback(err) : | ||
| callback(null, serverId); | ||
| }); | ||
| }); | ||
| } | ||
|
|
@@ -418,9 +443,9 @@ function rebootServer(server, callback) { | |
|
|
||
| var client = new ComputeManagementClient(self.azure.credentials, self.config.subscriptionId); | ||
| client.virtualMachines.restart(self.config.resourceGroup, serverId, function (err) { | ||
| return err | ||
| ? callback(err) | ||
| : callback(null, serverId); | ||
| return err ? | ||
| callback(err) : | ||
| callback(null, serverId); | ||
| }); | ||
| }); | ||
| } | ||
|
|
@@ -432,7 +457,9 @@ function rebootServer(server, callback) { | |
| */ | ||
| function renameServer(server, callback) { | ||
| return errs.handle( | ||
| errs.create({ message: 'Not supported by Azure.' }), | ||
| errs.create({ | ||
| message: 'Not supported by Azure.' | ||
| }), | ||
| callback | ||
| ); | ||
| } | ||
|
|
@@ -447,4 +474,4 @@ module.exports = { | |
| stopServer: stopServer, | ||
| rebootServer: rebootServer, | ||
| renameServer: renameServer | ||
| }; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| $username = $args[0] | ||
| $password = $args[1] | ||
| $securePassword = ConvertTo-SecureString $password -AsPlainText -Force | ||
| $credential = New-Object System.Management.Automation.PSCredential $username, $securePassword | ||
| Enable-PSRemoting -Force | ||
| $scriptPath = ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/DarwinJS/ChocoPackages/master/openssh/InstallChoco_and_win32-openssh_with_server.ps1')) | ||
|
Collaborator
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. Maybe it would be better to add this file to the repo or have a fork of the original repo so there are no surprises if it changes in the original repo |
||
| Invoke-Command -ScriptBlock ([scriptblock]::Create($scriptPath)) -Credential $credential -ComputerName localhost | ||
| Disable-PSRemoting -Force | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| #!/bin/bash | ||
|
Collaborator
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. Why add this file if it is not used? Did you mean to copy the original from DarwinJS/ChocoPackages?
Collaborator
Author
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. it is used by linux - see the previous comment |
||
| # Make sure you use a username that is lowercase. | ||
| USERNAME=$1 | ||
| echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers | ||
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.
General remark - I guess you are "beautifying" the code - but this should be done separarately from major changes since I can't tell what are the real changes and what are "white spaces"
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 is beautify - sorry about that, but as i said the real changes are very small. I will disable it for future use on this project