Add cluster transformations
Implement transformations that are applied to cluster attributes during environment cloning. Conversion from text to text_list type has been limited to dns_list and ntp_list keys only to keep predictable behavior. Change-Id: I1ff596f850bd42243697cad1c1c35f0cf1386376
This commit is contained in:
parent
163ce243fb
commit
95ff3a3598
|
@ -17,6 +17,7 @@ from nailgun.test import base as nailgun_test_base
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from .. import transformations
|
from .. import transformations
|
||||||
|
from ..transformations import cluster
|
||||||
|
|
||||||
|
|
||||||
class TestTransformations(nailgun_test_base.BaseUnitTest):
|
class TestTransformations(nailgun_test_base.BaseUnitTest):
|
||||||
|
@ -177,3 +178,44 @@ class TestLazy(nailgun_test_base.BaseUnitTest):
|
||||||
lazy_obj = transformations.Lazy(mgr_cls_mock)
|
lazy_obj = transformations.Lazy(mgr_cls_mock)
|
||||||
lazy_obj.apply()
|
lazy_obj.apply()
|
||||||
self.assertEqual(lazy_obj.apply, mgr_cls_mock.return_value.apply)
|
self.assertEqual(lazy_obj.apply, mgr_cls_mock.return_value.apply)
|
||||||
|
|
||||||
|
|
||||||
|
class TestClusterTransformers(nailgun_test_base.BaseUnitTest):
|
||||||
|
def setUp(self):
|
||||||
|
self.data = {
|
||||||
|
'editable': {
|
||||||
|
'external_dns': {
|
||||||
|
'dns_list': {'type': 'text', 'value': 'a,b,\nc, d'}},
|
||||||
|
'external_ntp': {
|
||||||
|
'ntp_list': {'type': 'text', 'value': 'a,b,\nc, d'}},
|
||||||
|
},
|
||||||
|
'generated': {
|
||||||
|
'provision': {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_dns_list(self):
|
||||||
|
res = cluster.transform_dns_list(self.data)
|
||||||
|
self.assertEqual(
|
||||||
|
res['editable']['external_dns']['dns_list'],
|
||||||
|
{'type': 'text_list', 'value': ['a', 'b', 'c', 'd']},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_ntp_list(self):
|
||||||
|
res = cluster.transform_ntp_list(self.data)
|
||||||
|
self.assertEqual(
|
||||||
|
res['editable']['external_ntp']['ntp_list'],
|
||||||
|
{'type': 'text_list', 'value': ['a', 'b', 'c', 'd']},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_provision(self):
|
||||||
|
res = cluster.drop_generated_provision(self.data)
|
||||||
|
self.assertNotIn('provision', res['generated'])
|
||||||
|
|
||||||
|
def test_manager(self):
|
||||||
|
man = cluster.Manager() # verify default config and entry points
|
||||||
|
self.assertEqual(man.transformers, [(version.StrictVersion('9.0'), [
|
||||||
|
cluster.transform_dns_list,
|
||||||
|
cluster.transform_ntp_list,
|
||||||
|
cluster.drop_generated_provision,
|
||||||
|
])])
|
||||||
|
|
|
@ -50,7 +50,7 @@ class TestUpgradeHelperCloneCluster(base_tests.BaseCloneClusterTest):
|
||||||
{"metadata": "src_fake",
|
{"metadata": "src_fake",
|
||||||
"key":
|
"key":
|
||||||
{"type": "text",
|
{"type": "text",
|
||||||
"value": "fake1, fake2,fake3 , fake4"},
|
"value": "fake"},
|
||||||
"src_key": "src_data"
|
"src_key": "src_data"
|
||||||
},
|
},
|
||||||
"repo_setup": "src_data"
|
"repo_setup": "src_data"
|
||||||
|
@ -69,9 +69,6 @@ class TestUpgradeHelperCloneCluster(base_tests.BaseCloneClusterTest):
|
||||||
result = upgrade.merge_attributes(
|
result = upgrade.merge_attributes(
|
||||||
src_editable_attrs, new_editable_attrs
|
src_editable_attrs, new_editable_attrs
|
||||||
)
|
)
|
||||||
new_editable_attrs["test"]["key"]["value"] = [
|
|
||||||
"fake1", "fake2", "fake3", "fake4"
|
|
||||||
]
|
|
||||||
self.assertEqual(result, new_editable_attrs)
|
self.assertEqual(result, new_editable_attrs)
|
||||||
|
|
||||||
def test_create_cluster_clone(self):
|
def test_create_cluster_clone(self):
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from cluster_upgrade import transformations
|
||||||
|
|
||||||
|
# NOTE: In the mitaka-9.0 release types of values dns_list and
|
||||||
|
# ntp_list were changed from 'text'
|
||||||
|
# (a string of comma-separated IP-addresses)
|
||||||
|
# to 'text_list' (a list of strings of IP-addresses).
|
||||||
|
|
||||||
|
|
||||||
|
def transform_to_text_list(data):
|
||||||
|
if data['type'] == 'text':
|
||||||
|
data['type'] = 'text_list'
|
||||||
|
data['value'] = [
|
||||||
|
part.strip() for part in data['value'].split(',')
|
||||||
|
]
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def transform_dns_list(data):
|
||||||
|
dns_list = data['editable']['external_dns']['dns_list']
|
||||||
|
transform_to_text_list(dns_list)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def transform_ntp_list(data):
|
||||||
|
ntp_list = data['editable']['external_ntp']['ntp_list']
|
||||||
|
transform_to_text_list(ntp_list)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def drop_generated_provision(data):
|
||||||
|
data['generated'].pop('provision', None)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class Manager(transformations.Manager):
|
||||||
|
default_config = {
|
||||||
|
'9.0': ['dns_list', 'ntp_list', 'drop_provision'],
|
||||||
|
}
|
||||||
|
name = 'cluster'
|
|
@ -25,7 +25,9 @@ from nailgun.extensions.network_manager.objects.serializers import \
|
||||||
from nailgun import objects
|
from nailgun import objects
|
||||||
from nailgun import utils
|
from nailgun import utils
|
||||||
|
|
||||||
|
from . import transformations # That's weird, but that's how hacking likes
|
||||||
from .objects import adapters
|
from .objects import adapters
|
||||||
|
from .transformations import cluster as cluster_trs
|
||||||
|
|
||||||
|
|
||||||
def merge_attributes(a, b):
|
def merge_attributes(a, b):
|
||||||
|
@ -42,25 +44,9 @@ def merge_attributes(a, b):
|
||||||
for key, values in six.iteritems(pairs):
|
for key, values in six.iteritems(pairs):
|
||||||
if key != "metadata" and key in a_values:
|
if key != "metadata" and key in a_values:
|
||||||
values["value"] = a_values[key]["value"]
|
values["value"] = a_values[key]["value"]
|
||||||
# NOTE: In the mitaka-9.0 release types of values dns_list and
|
|
||||||
# ntp_list were changed from 'text'
|
|
||||||
# (a string of comma-separated IP-addresses)
|
|
||||||
# to 'text_list' (a list of strings of IP-addresses).
|
|
||||||
if a_values[key]['type'] == 'text' and \
|
|
||||||
values['type'] == 'text_list':
|
|
||||||
values["value"] = [
|
|
||||||
value.strip() for value in values['value'].split(',')
|
|
||||||
]
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
def merge_generated_attrs(new_attrs, orig_attrs):
|
|
||||||
# skip attributes that should be generated for new cluster
|
|
||||||
attrs = copy.deepcopy(orig_attrs)
|
|
||||||
attrs.pop('provision', None)
|
|
||||||
return utils.dict_merge(new_attrs, attrs)
|
|
||||||
|
|
||||||
|
|
||||||
def merge_nets(a, b):
|
def merge_nets(a, b):
|
||||||
new_settings = copy.deepcopy(b)
|
new_settings = copy.deepcopy(b)
|
||||||
source_networks = dict((n["name"], n) for n in a["networks"])
|
source_networks = dict((n["name"], n) for n in a["networks"])
|
||||||
|
@ -88,6 +74,7 @@ class UpgradeHelper(object):
|
||||||
consts.CLUSTER_NET_PROVIDERS.nova_network:
|
consts.CLUSTER_NET_PROVIDERS.nova_network:
|
||||||
network_configuration.NovaNetworkConfigurationSerializer,
|
network_configuration.NovaNetworkConfigurationSerializer,
|
||||||
}
|
}
|
||||||
|
cluster_transformations = transformations.Lazy(cluster_trs.Manager)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clone_cluster(cls, orig_cluster, data):
|
def clone_cluster(cls, orig_cluster, data):
|
||||||
|
@ -111,20 +98,24 @@ class UpgradeHelper(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def copy_attributes(cls, orig_cluster, new_cluster):
|
def copy_attributes(cls, orig_cluster, new_cluster):
|
||||||
# TODO(akscram): Attributes should be copied including
|
attrs = cls.cluster_transformations.apply(
|
||||||
# borderline cases when some parameters are
|
orig_cluster.release.environment_version,
|
||||||
# renamed or moved into plugins. Also, we should
|
new_cluster.release.environment_version,
|
||||||
# to keep special steps in copying of parameters
|
{
|
||||||
# that know how to translate parameters from one
|
'editable': orig_cluster.editable_attrs,
|
||||||
# version to another. A set of this kind of steps
|
'generated': orig_cluster.generated_attrs,
|
||||||
# should define an upgrade path of a particular
|
},
|
||||||
# cluster.
|
)
|
||||||
new_cluster.generated_attrs = merge_generated_attrs(
|
|
||||||
|
new_cluster.generated_attrs = utils.dict_merge(
|
||||||
new_cluster.generated_attrs,
|
new_cluster.generated_attrs,
|
||||||
orig_cluster.generated_attrs)
|
attrs['generated'],
|
||||||
|
)
|
||||||
|
|
||||||
new_cluster.editable_attrs = merge_attributes(
|
new_cluster.editable_attrs = merge_attributes(
|
||||||
orig_cluster.editable_attrs,
|
attrs['editable'],
|
||||||
new_cluster.editable_attrs)
|
new_cluster.editable_attrs,
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def change_env_settings(cls, orig_cluster, new_cluster):
|
def change_env_settings(cls, orig_cluster, new_cluster):
|
||||||
|
|
|
@ -25,3 +25,7 @@ packages =
|
||||||
[entry_points]
|
[entry_points]
|
||||||
nailgun.extensions =
|
nailgun.extensions =
|
||||||
cluster_upgrade = cluster_upgrade.extension:ClusterUpgradeExtension
|
cluster_upgrade = cluster_upgrade.extension:ClusterUpgradeExtension
|
||||||
|
nailgun.cluster_upgrade.transformations.cluster.9.0 =
|
||||||
|
dns_list = cluster_upgrade.transformations.cluster:transform_dns_list
|
||||||
|
ntp_list = cluster_upgrade.transformations.cluster:transform_ntp_list
|
||||||
|
drop_provision = cluster_upgrade.transformations.cluster:drop_generated_provision
|
||||||
|
|
Loading…
Reference in New Issue