Add user-data/custom-data to Azure driver

This is the relatively common feature that allows users to include
cloud_init or similar data.  Azure has two versions of it, user-data
and custom-data.  For Nodepool's purpose they are similar, but a user
may prefer one or the other.

Also adds missing docs for the existing tags attribute.

Change-Id: Ia2f78a827c1909cc527733013167b2f3b5db18a3
This commit is contained in:
James E. Blair 2021-10-18 16:30:51 -07:00
parent 736b7c5905
commit c3c0c6d538
7 changed files with 75 additions and 21 deletions

View File

@ -510,7 +510,29 @@ section of the configuration.
list on `azure.microsoft.com`_ for the list of sizes list on `azure.microsoft.com`_ for the list of sizes
availabile in each region. availabile in each region.
.. attr:: tags
:type: dict
:default: None
A dictionary of tags to add to newly created VMs.
.. attr:: user-data
:type: str
:default: None
The `Azure User Data`_ value for newly created VMs.
.. attr:: custom-data
:type: str
:default: None
The `Azure Custom Data`_ value for newly created VMs.
.. _`Azure CLI`: https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest .. _`Azure CLI`: https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest
.. _azure.microsoft.com: https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines .. _azure.microsoft.com: https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines
.. _`Azure User Data`: https://docs.microsoft.com/en-us/azure/virtual-machines/user-data
.. _`Azure Custom Data`: https://docs.microsoft.com/en-us/azure/virtual-machines/custom-data

View File

@ -646,30 +646,35 @@ class AzureAdapter(statemachine.Adapter):
} }
os_profile['adminUsername'] = image.username os_profile['adminUsername'] = image.username
os_profile['linuxConfiguration'] = linux_config os_profile['linuxConfiguration'] = linux_config
if label.custom_data:
os_profile['customData'] = label.custom_data
spec = {
'location': self.provider.location,
'tags': tags,
'properties': {
'osProfile': os_profile,
'hardwareProfile': {
'vmSize': label.hardware_profile["vm-size"]
},
'storageProfile': {
'imageReference': image_reference,
},
'networkProfile': {
'networkInterfaces': [{
'id': nic['id'],
'properties': {
'primary': True,
}
}]
},
},
}
if label.user_data:
spec['properties']['userData'] = label.user_data
with self.rate_limiter: with self.rate_limiter:
return self.azul.virtual_machines.create( return self.azul.virtual_machines.create(
self.resource_group, hostname, { self.resource_group, hostname, spec)
'location': self.provider.location,
'tags': tags,
'properties': {
'osProfile': os_profile,
'hardwareProfile': {
'vmSize': label.hardware_profile["vm-size"]
},
'storageProfile': {
'imageReference': image_reference,
},
'networkProfile': {
'networkInterfaces': [{
'id': nic['id'],
'properties': {
'primary': True,
}
}]
},
},
})
def _deleteVirtualMachine(self, name): def _deleteVirtualMachine(self, name):
for vm in self._listVirtualMachines(): for vm in self._listVirtualMachines():

View File

@ -16,6 +16,7 @@
# limitations under the License. # limitations under the License.
import voluptuous as v import voluptuous as v
import base64
import os import os
from nodepool.driver import ConfigPool from nodepool.driver import ConfigPool
@ -143,6 +144,13 @@ class AzureLabel(ConfigValue):
self.hardware_profile = label['hardware-profile'] self.hardware_profile = label['hardware-profile']
self.tags = label.get('tags', {}) self.tags = label.get('tags', {})
self.user_data = self._encodeData(label.get('user-data', None))
self.custom_data = self._encodeData(label.get('custom-data', None))
def _encodeData(self, s):
if not s:
return None
return base64.b64encode(s.encode('utf8')).decode('utf8')
@staticmethod @staticmethod
def getSchema(): def getSchema():
@ -156,6 +164,8 @@ class AzureLabel(ConfigValue):
'diskimage': str, 'diskimage': str,
v.Required('hardware-profile'): azure_hardware_profile, v.Required('hardware-profile'): azure_hardware_profile,
'tags': dict, 'tags': dict,
'user-data': str,
'custom-data': str,
} }

View File

@ -49,3 +49,5 @@ providers:
department: R&D department: R&D
team: DevOps team: DevOps
systemPurpose: CI systemPurpose: CI
user-data: "This is the user data"
custom-data: "This is the custom data"

View File

@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import copy
import json import json
import time import time
import os import os
@ -33,6 +34,7 @@ class CRUDManager:
def __init__(self, cloud): def __init__(self, cloud):
self.cloud = cloud self.cloud = cloud
self.items = [] self.items = []
self.requests = []
def list(self, request): def list(self, request):
resp = {'value': self.items} resp = {'value': self.items}
@ -139,6 +141,7 @@ class VirtualMachinesCRUD(CRUDManager):
def put(self, request): def put(self, request):
data = json.loads(request.body) data = json.loads(request.body)
self.requests.append(copy.deepcopy(data))
url = urllib.parse.urlparse(request.path_url) url = urllib.parse.urlparse(request.path_url)
name = url.path.split('/')[-1] name = url.path.split('/')[-1]
data['id'] = url.path data['id'] = url.path

View File

@ -58,6 +58,14 @@ class TestDriverAzure(tests.DBTestCase):
self.assertEqual(node.attributes, self.assertEqual(node.attributes,
{'key1': 'value1', 'key2': 'value2'}) {'key1': 'value1', 'key2': 'value2'})
self.assertEqual(node.host_keys, ['ssh-rsa FAKEKEY']) self.assertEqual(node.host_keys, ['ssh-rsa FAKEKEY'])
self.assertEqual(
self.fake_azure.crud['Microsoft.Compute/virtualMachines'].
items[0]['properties']['osProfile']['customData'],
'VGhpcyBpcyB0aGUgY3VzdG9tIGRhdGE=') # This is the custom data
self.assertEqual(
self.fake_azure.crud['Microsoft.Compute/virtualMachines'].
requests[0]['properties']['userData'],
'VGhpcyBpcyB0aGUgdXNlciBkYXRh') # This is the user data
def test_azure_diskimage(self): def test_azure_diskimage(self):
configfile = self.setup_config( configfile = self.setup_config(

View File

@ -0,0 +1,4 @@
---
features:
- |
The Azure driver now supports user-data and custom-data.