Add metadata interface for instance data
Some plugins, like the userdata execution plugin, need a standard model for the instance data, which can be applied by templating engines like jinja to the userdata. This way, a user can use this feature to customize her userdata scripts with values that are specific to that instance runtime env or cloud platform. The instance data structure is based on the cloud-init specifications: https://cloudinit.readthedocs.io/en/latest/topics/instancedata.html The v1 namespace contains a subset of the cloud-init specs for the instance data. The ds.meta_data namespace contains all the values the v1 namespace contains, in order to be compatible with cloud-init, plus a subset of other instance data. Change-Id: I5c529498f06fe3c86f7fa3c20fdf3091840c4041
This commit is contained in:
parent
c31c5b99f1
commit
551c4eb318
@ -14,6 +14,7 @@
|
||||
|
||||
|
||||
import abc
|
||||
import copy
|
||||
import gzip
|
||||
import io
|
||||
import time
|
||||
@ -221,6 +222,45 @@ class BaseMetadataService(object):
|
||||
def get_ephemeral_disk_data_loss_warning(self):
|
||||
raise NotExistingMetadataException()
|
||||
|
||||
def get_instance_data(self):
|
||||
"""Returns a dictionary with instance data from the metadata source
|
||||
|
||||
The instance data structure is based on the cloud-init specifications:
|
||||
https://cloudinit.readthedocs.io/en/latest/topics/instancedata.html
|
||||
|
||||
The v1 namespace contains a subset of the cloud-init standard
|
||||
for the instance data. In the future, it should reach parity with the
|
||||
cloud-init standard.
|
||||
|
||||
The ds.meta_data namespace contains all the values the v1 namespace
|
||||
contains, in order to be compatible with cloud-init, plus a subset of
|
||||
other instance data.
|
||||
The ds namespace can change without prior notice and should not be
|
||||
used in production.
|
||||
"""
|
||||
|
||||
instance_id = self.get_instance_id()
|
||||
hostname = self.get_host_name()
|
||||
|
||||
v1_data = {
|
||||
"instance_id": instance_id,
|
||||
"local_hostname": hostname,
|
||||
"public_ssh_keys": self.get_public_keys()
|
||||
}
|
||||
|
||||
# Copy the v1 data to the ds.meta_data and add more fields
|
||||
ds_meta_data = copy.deepcopy(v1_data)
|
||||
ds_meta_data.update({
|
||||
"hostname": hostname
|
||||
})
|
||||
|
||||
return {
|
||||
"v1": v1_data,
|
||||
"ds": {
|
||||
"meta_data": ds_meta_data,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class BaseHTTPMetadataService(BaseMetadataService):
|
||||
|
||||
|
@ -61,6 +61,38 @@ class TestBase(unittest.TestCase):
|
||||
result = self._service.get_user_pwd_encryption_key()
|
||||
self.assertEqual(result, mock_get_public_keys.return_value[0])
|
||||
|
||||
@mock.patch('cloudbaseinit.metadata.services.base.'
|
||||
'BaseMetadataService.get_public_keys')
|
||||
@mock.patch('cloudbaseinit.metadata.services.base.'
|
||||
'BaseMetadataService.get_host_name')
|
||||
@mock.patch('cloudbaseinit.metadata.services.base.'
|
||||
'BaseMetadataService.get_instance_id')
|
||||
def test_get_instance_data(self, mock_instance_id, mock_hostname,
|
||||
mock_public_keys):
|
||||
fake_instance_id = 'id'
|
||||
mock_instance_id.return_value = fake_instance_id
|
||||
fake_hostname = 'host'
|
||||
mock_hostname.return_value = fake_hostname
|
||||
fake_keys = ['ssh1', 'ssh2']
|
||||
mock_public_keys.return_value = fake_keys
|
||||
|
||||
expected_response = {
|
||||
'v1': {
|
||||
"instance_id": fake_instance_id,
|
||||
"local_hostname": fake_hostname,
|
||||
"public_ssh_keys": fake_keys
|
||||
},
|
||||
'ds': {
|
||||
'meta_data': {
|
||||
"instance_id": fake_instance_id,
|
||||
"local_hostname": fake_hostname,
|
||||
"public_ssh_keys": fake_keys,
|
||||
"hostname": fake_hostname
|
||||
},
|
||||
}
|
||||
}
|
||||
self.assertEqual(expected_response, self._service.get_instance_data())
|
||||
|
||||
|
||||
class TestBaseHTTPMetadataService(unittest.TestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user