Merge pull request #47648 from bloomberg/provider-override

salt-cloud: allow map nodes to override provider
This commit is contained in:
Daniel Wallace 2018-05-17 13:24:49 -05:00 committed by GitHub
commit 567395f4fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 38 deletions

View File

@ -1916,7 +1916,8 @@ class Map(Cloud):
pmap = self.map_providers_parallel(cached=cached)
exist = set()
defined = set()
for profile_name, nodes in six.iteritems(self.rendered_map):
rendered_map = copy.deepcopy(self.rendered_map)
for profile_name, nodes in six.iteritems(rendered_map):
if profile_name not in self.opts['profiles']:
msg = (
'The required profile, \'{0}\', defined in the map '
@ -1934,21 +1935,23 @@ class Map(Cloud):
profile_data = self.opts['profiles'].get(profile_name)
# Get associated provider data, in case something like size
# or image is specified in the provider file. See issue #32510.
alias, driver = profile_data.get('provider').split(':')
provider_details = self.opts['providers'][alias][driver].copy()
del provider_details['profiles']
# Update the provider details information with profile data
# Profile data should override provider data, if defined.
# This keeps map file data definitions consistent with -p usage.
provider_details.update(profile_data)
profile_data = provider_details
for nodename, overrides in six.iteritems(nodes):
# Get the VM name
nodedata = copy.deepcopy(profile_data)
# Get associated provider data, in case something like size
# or image is specified in the provider file. See issue #32510.
if 'provider' in overrides and overrides['provider'] != profile_data['provider']:
alias, driver = overrides.get('provider').split(':')
else:
alias, driver = profile_data.get('provider').split(':')
provider_details = copy.deepcopy(self.opts['providers'][alias][driver])
del provider_details['profiles']
# Update the provider details information with profile data
# Profile data and node overrides should override provider data, if defined.
# This keeps map file data definitions consistent with -p usage.
salt.utils.dictupdate.update(provider_details, profile_data)
nodedata = copy.deepcopy(provider_details)
# Update profile data with the map overrides
for setting in ('grains', 'master', 'minion', 'volumes',
'requires'):

View File

@ -21,25 +21,27 @@ import salt.cloud
EXAMPLE_PROVIDERS = {
'nyc_vcenter': {'vmware': {'driver': 'vmware',
'password': '123456',
'profiles': {'nyc-vm': {'cluster': 'nycvirt',
'datastore': 'datastore1',
'devices': {'disk': {'Hard disk 1': {'controller': 'SCSI controller 1',
'size': 20}},
'network': {'Network Adapter 1': {'mac': '44:44:44:44:44:42',
'name': 'vlan50',
'switch_type': 'standard'}},
'scsi': {'SCSI controller 1': {'type': 'paravirtual'}}},
'extra_config': {'mem.hotadd': 'yes'},
'folder': 'coreinfra',
'image': 'rhel6_64Guest',
'memory': '8GB',
'num_cpus': 2,
'power_on': True,
'profile': 'nyc-vm',
'provider': 'nyc_vcenter:vmware',
'resourcepool': 'Resources'}},
'url': 'vca1.saltstack.com',
'user': 'root'}}
'minion': {
'master': 'providermaster',
'grains': {
'providergrain': True
}
},
'profiles': {},
'user': 'root'}},
'nj_vcenter': {'vmware': {'driver': 'vmware',
'password': '333',
'profiles': {},
'minion': {
'master': 'providermaster',
'grains': {
'providergrain': True
}
},
'image': 'rhel6_64prod',
'url': 'vca2.saltstack.com',
'user': 'root'}}
}
EXAMPLE_PROFILES = {
@ -47,19 +49,35 @@ EXAMPLE_PROFILES = {
'datastore': 'datastore1',
'devices': {'disk': {'Hard disk 1': {'controller': 'SCSI controller 1',
'size': 20}},
'network': {'Network Adapter 1': {'mac': '44:44:44:44:44:42',
'network': {'Network Adapter 1': {'mac': '88:88:88:88:88:42',
'name': 'vlan50',
'switch_type': 'standard'}},
'scsi': {'SCSI controller 1': {'type': 'paravirtual'}}},
'extra_config': {'mem.hotadd': 'yes'},
'folder': 'coreinfra',
'image': 'rhel6_64Guest',
'minion': {
'master': 'profilemaster',
'grains': {
'profilegrain': True
}
},
'memory': '8GB',
'num_cpus': 2,
'power_on': True,
'profile': 'nyc-vm',
'provider': 'nyc_vcenter:vmware',
'resourcepool': 'Resources'}
'resourcepool': 'Resources'},
'nj-vm': {'cluster': 'njvirt',
'folder': 'coreinfra',
'image': 'rhel6_64Guest',
'memory': '8GB',
'num_cpus': 2,
'power_on': True,
'profile': 'nj-vm',
'provider': 'nj_vcenter:vmware',
'resourcepool': 'Resources'},
}
EXAMPLE_MAP = {
@ -67,7 +85,19 @@ EXAMPLE_MAP = {
'devices': {'disk': {'Hard disk 1': {'size': 40}},
'network': {'Network Adapter 1': {'mac': '22:4a:b2:92:b3:eb'}}},
'memory': '16GB',
'name': 'db1'}}
'minion': {
'master': 'mapmaster',
'grains': {
'mapgrain': True
}
},
'name': 'db1'},
'db2': {'name': 'db2',
'password': '456',
'provider': 'nj_vcenter:vmware'}},
'nj-vm': {'db3': {'name': 'db3',
'password': '789',
}}
}
@ -87,6 +117,7 @@ class MapConfTest(TestCase):
opts = {'extension_modules': '/var/cache/salt/master/extmods',
'providers': EXAMPLE_PROVIDERS, 'profiles': EXAMPLE_PROFILES}
cloud_map = salt.cloud.Map(opts)
merged_profile = {
'create': {'db1': {'cluster': 'nycvirt',
'cpus': 4,
@ -102,6 +133,10 @@ class MapConfTest(TestCase):
'folder': 'coreinfra',
'image': 'rhel6_64Guest',
'memory': '16GB',
'minion': {'grains': {'mapgrain': True,
'profilegrain': True,
'providergrain': True},
'master': 'mapmaster'},
'name': 'db1',
'num_cpus': 2,
'password': '123456',
@ -110,6 +145,59 @@ class MapConfTest(TestCase):
'provider': 'nyc_vcenter:vmware',
'resourcepool': 'Resources',
'url': 'vca1.saltstack.com',
'user': 'root'}}
'user': 'root'},
'db2': {'cluster': 'nycvirt',
'datastore': 'datastore1',
'devices': {'disk': {'Hard disk 1': {'controller': 'SCSI controller 1',
'size': 20}},
'network': {'Network Adapter 1': {'mac': '88:88:88:88:88:42',
'name': 'vlan50',
'switch_type': 'standard'}},
'scsi': {'SCSI controller 1': {'type': 'paravirtual'}}},
'driver': 'vmware',
'extra_config': {'mem.hotadd': 'yes'},
'folder': 'coreinfra',
'image': 'rhel6_64Guest',
'memory': '8GB',
'minion': {'grains': {'profilegrain': True,
'providergrain': True},
'master': 'profilemaster'},
'name': 'db2',
'num_cpus': 2,
'password': '456',
'power_on': True,
'profile': 'nyc-vm',
'provider': 'nj_vcenter:vmware',
'resourcepool': 'Resources',
'url': 'vca2.saltstack.com',
'user': 'root'},
'db3': {'cluster': 'njvirt',
'driver': 'vmware',
'folder': 'coreinfra',
'image': 'rhel6_64Guest',
'memory': '8GB',
'minion': {'grains': {'providergrain': True},
'master': 'providermaster'},
'name': 'db3',
'num_cpus': 2,
'password': '789',
'power_on': True,
'profile': 'nj-vm',
'provider': 'nj_vcenter:vmware',
'resourcepool': 'Resources',
'url': 'vca2.saltstack.com',
'user': 'root'}}
}
self.assertEqual(cloud_map.map_data(), merged_profile)
# what we assert above w.r.t db2 using nj_vcenter:vmware provider:
# - url is from the overriden nj_vcenter provider, not nyc_vcenter
# - image from provider is still overridden by the nyc-vm profile
# - password from map override is still overriding both the provider and profile password
#
# what we assert above about grain handling ( and provider/profile/map data in general )
# - provider grains are able to be overridden by profile data
# - provider grain sare overridden by map data
# - profile data is overriden by map data
# ie, the provider->profile->map inheritance works as expected
map_data = cloud_map.map_data()
self.assertEqual(map_data, merged_profile)