Пример #1
0
 def put(self):
     self.check_policy('managesf.resources:apply')
     infos = request.json if request.content_length else {}
     eng = SFResourceBackendEngine(
         os.path.join(conf.resources['workdir'], 'apply'),
         conf.resources['subdir'])
     if not infos or 'COMMIT' in infos:
         commit = infos.get('COMMIT', 'master')
         status, logs = eng.apply(conf.resources['master_repo'],
                                  '%s^1' % commit,
                                  conf.resources['master_repo'], commit)
     else:
         try:
             prev = infos.get('prev', None)
             new = infos.get('new', None)
             if not prev or not new:
                 raise Exception
         except Exception:
             response.status = 400
             return [
                 'Unable to find the "new" and/or "prev" '
                 'keys in the json payload'
             ]
         status, logs = eng.direct_apply(prev, new)
     if not status:
         response.status = 409
     else:
         response.status = 201
     return logs
Пример #2
0
    def test_get_resources_priority(self):
        class A(BaseResource):
            PRIORITY = 60
            PRIMARY_KEY = None

        class B(BaseResource):
            PRIORITY = 40
            PRIMARY_KEY = None

        class C(BaseResource):
            PRIORITY = 55
            PRIMARY_KEY = None

        en = SFResourceBackendEngine(None, None)
        with patch.dict(engine.MAPPING,
                        {'dummies': Dummy,
                         'A': A,
                         'B': B,
                         'C': C}, clear=True):
            # Resource callback will be called in that
            # order A, C, dummies, B
            self.assertEqual([('A', 60),
                              ('C', 55),
                              ('dummies', 50),
                              ('B', 40)],
                             en._get_resources_priority())
            self.assertTrue(len(en._get_resources_priority()), 4)
Пример #3
0
 def put(self):
     self.check_policy('managesf.resources:apply')
     infos = request.json if request.content_length else {}
     eng = SFResourceBackendEngine(
         os.path.join(conf.resources['workdir'], 'apply'),
         conf.resources['subdir'])
     if not infos or 'COMMIT' in infos:
         commit = infos.get('COMMIT', 'master')
         status, logs = eng.apply(conf.resources['master_repo'],
                                  '%s^1' % commit,
                                  conf.resources['master_repo'],
                                  commit)
     else:
         try:
             prev = infos.get('prev', None)
             new = infos.get('new', None)
             if not prev or not new:
                 raise Exception
         except Exception:
             response.status = 400
             return ['Unable to find the "new" and/or "prev" '
                     'keys in the json payload']
         status, logs = eng.direct_apply(prev, new)
     if not status:
         response.status = 409
     else:
         response.status = 201
     return logs
Пример #4
0
 def get(self, **kwargs):
     self.check_policy('managesf.resources:get')
     eng = SFResourceBackendEngine(
         os.path.join(conf.resources['workdir'], 'read'),
         conf.resources['subdir'])
     if kwargs.get('get_missing_resources', None) == 'true':
         return eng.get_missing_resources(conf.resources['master_repo'],
                                          'master')
     else:
         return eng.get(conf.resources['master_repo'], 'master')
Пример #5
0
 def test_get(self):
     with patch('managesf.model.yamlbkd.yamlbackend.'
                'YAMLBackend.__init__') as i, \
             patch('managesf.model.yamlbkd.yamlbackend.'
                   'YAMLBackend.get_data') as g:
         i.return_value = None
         g.return_value = True
         eng = SFResourceBackendEngine('/tmp/adir', None)
         data = eng.get(None, None)
         self.assertTrue(data)
Пример #6
0
 def test_load_resources_data(self):
     with patch('managesf.model.yamlbkd.engine.'
                'SFResourceBackendEngine._load_resource_data') as l:
         l.return_value = {}
         en = SFResourceBackendEngine(None, None)
         en._load_resources_data(
             'http://sftests.com/r/config.git',
             'heads/master',
             'http://sftests.com/r/config.git',
             'changes/99/899/1')
     self.assertEqual(len(l.mock_calls), 2)
Пример #7
0
    def test_check_deps_constraints(self):
        class Master(BaseResource):
            MODEL_TYPE = 'master'
            MODEL = {
                'name': (str, "+*", True, None, True, "desc"),
                'key1': (str, "+*", True, None, True, "desc"),
                'key2': (list, "+*", True, None, True, "desc"),
            }
            PRIORITY = 40
            PRIMARY_KEY = None

            def get_deps(self):
                deps = {'dummies': set([])}
                deps['dummies'].add(self.resource['key1'])
                for e in self.resource['key2']:
                    deps['dummies'].add(e)
                return deps

        new = {
            'resources': {
                'dummies': {
                    'd1': {
                        'name': 'dummy1',
                        'namespace': 'space',
                    },
                    'd2': {
                        'name': 'dummy2',
                        'namespace': 'space',
                    },
                    'd3': {
                        'name': 'dummy3',
                        'namespace': 'space',
                    },
                },
                'masters': {
                    'm1': {
                        'key1': 'd1',
                        'key2': ['d1', 'd2'],
                    }
                }
            }
        }

        en = SFResourceBackendEngine(None, None)
        with patch.dict(engine.MAPPING,
                        {'dummies': Dummy,
                         'masters': Master}):
            en._check_deps_constraints(new)
            # Add an unknown dependency
            new['resources']['masters']['m1']['key1'] = 'd4'
            self.assertRaises(ResourceDepsException,
                              en._check_deps_constraints,
                              new)
Пример #8
0
 def get(self, **kwargs):
     self.check_policy('managesf.resources:get')
     eng = SFResourceBackendEngine(
         os.path.join(conf.resources['workdir'], 'read'),
         conf.resources['subdir'])
     if kwargs.get('get_missing_resources', None) == 'true':
         return eng.get_missing_resources(
             conf.resources['master_repo'],
             'master')
     else:
         return eng.get(
             conf.resources['master_repo'],
             'master')
Пример #9
0
    def test_check_unicity_constraints(self):
        class Master(BaseResource):
            MODEL_TYPE = 'master'
            MODEL = {
                'name': (str, "+*", True, None, True, "desc"),
            }
            PRIORITY = 40
            PRIMARY_KEY = 'name'

        new = {
            'resources': {
                'masters': {
                    'm1': {
                        'name': 'ichiban',
                    },
                    'm2': {
                        'name': 'ichiban',
                    }
                }
            }
        }
        en = SFResourceBackendEngine(None, None)
        with patch.dict(engine.MAPPING,
                        {'masters': Master}):
            self.assertRaises(ResourceUnicityException,
                              en._check_unicity_constraints,
                              new)
Пример #10
0
 def post(self):
     self.check_policy('managesf.resources:validate')
     infos = request.json if request.content_length else {}
     zuul_url = infos.get('zuul_url', None)
     zuul_ref = infos.get('zuul_ref', None)
     if not all([zuul_url, zuul_ref]):
         abort(400, detail="Request content invalid")
     eng = SFResourceBackendEngine(
         os.path.join(conf.resources['workdir'], 'validate'),
         conf.resources['subdir'])
     status, logs = eng.validate(conf.resources['master_repo'], 'master',
                                 zuul_url, zuul_ref)
     if not status:
         response.status = 409
     else:
         response.status = 200
     return logs
Пример #11
0
 def post(self):
     self.check_policy('managesf.resources:validate')
     infos = request.json if request.content_length else {}
     zuul_url = infos.get('zuul_url', None)
     zuul_ref = infos.get('zuul_ref', None)
     if not all([zuul_url, zuul_ref]):
         abort(400, detail="Request content invalid")
     eng = SFResourceBackendEngine(
         os.path.join(conf.resources['workdir'], 'validate'),
         conf.resources['subdir'])
     status, logs = eng.validate(conf.resources['master_repo'],
                                 'master', zuul_url, zuul_ref)
     if not status:
         response.status = 409
     else:
         response.status = 200
     return logs
Пример #12
0
 def test_load_resource_data(self):
     path = tempfile.mkdtemp()
     self.to_delete.append(path)
     with patch('managesf.model.yamlbkd.yamlbackend.'
                'YAMLBackend.__init__') as i, \
             patch('managesf.model.yamlbkd.yamlbackend.'
                   'YAMLBackend.get_data') as g:
         i.return_value = None
         g.return_value = {}
         en = SFResourceBackendEngine(path,
                                      'resources')
         en._load_resource_data(
             'http://sftests.com/r/config.git',
             'heads/master', 'mark')
     self.assertTrue(os.path.isdir(
         os.path.join(path, 'mark')))
     self.assertTrue(i.called)
     self.assertTrue(g.called)
Пример #13
0
 def test_validate_changes(self):
     eng = SFResourceBackendEngine(None, None)
     validation_logs = []
     with patch.dict(engine.MAPPING, {'dummies': Dummy}):
         with patch.object(Dummy, 'validate') as v:
             changes = {'dummies': {'create': {'myprojectid': {}}}}
             eng._validate_changes(changes, validation_logs, {})
             self.assertTrue(v.called)
             v.reset_mock()
             changes = {'dummies': {'update': {
                 'myprojectid': {'data': {}, 'changed': []}}}}
             eng._validate_changes(changes, validation_logs, {})
             self.assertTrue(v.called)
             with patch.object(Dummy, 'is_mutable') as i:
                 v.reset_mock()
                 changes = {'dummies': {'update': {
                     'myprojectid': {'data': {}, 'changed': ['name']}}}}
                 eng._validate_changes(changes, validation_logs, {})
                 self.assertTrue(v.called)
                 self.assertTrue(i.called)
         # Be sure we have 3 validation msgs
         self.assertTrue(len(validation_logs), 3)
         validation_logs = []
         with patch.object(Dummy, 'validate') as v:
             v.side_effect = ResourceInvalidException('')
             changes = {'dummies': {'create': {'myprojectid': {}}}}
             self.assertRaises(ResourceInvalidException,
                               eng._validate_changes,
                               changes,
                               validation_logs,
                               {})
         with patch.object(Dummy, 'validate') as v:
             v.side_effect = ModelInvalidException('')
             changes = {'dummies': {'create': {'myprojectid': {}}}}
             self.assertRaises(ModelInvalidException,
                               eng._validate_changes,
                               changes,
                               validation_logs,
                               {})
         # Verify extra validations will be handled
         validation_logs = []
         with patch('managesf.model.yamlbkd.resources.'
                    'dummy.DummyOps.extra_validations') as xv:
             xv.return_value = ['error msg1', ' error msg2']
             changes = {'dummies': {'create': {'myprojectid': {
                 'namespace': 'sf', 'name': 'p1'}}}}
             self.assertRaises(ResourceInvalidException,
                               eng._validate_changes,
                               changes,
                               validation_logs,
                               {})
             self.assertTrue(xv.called)
             self.assertListEqual(['error msg1', ' error msg2'],
                                  validation_logs)
Пример #14
0
 def test_apply(self):
     path = tempfile.mkdtemp()
     self.to_delete.append(path)
     with patch('managesf.model.yamlbkd.engine.'
                'SFResourceBackendEngine._load_resources_data') as l, \
             patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._get_data_diff') as g, \
             patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                   '_resolv_resources_need_refresh') as r, \
             patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._apply_changes') as a:
         l.return_value = (None, None)
         a.return_value = False
         r.return_value = []
         eng = SFResourceBackendEngine(path, None)
         status, logs = eng.apply(None, None, None, None)
         self.assertTrue(l.called)
         self.assertTrue(g.called)
         self.assertTrue(r.called)
         self.assertTrue(a.called)
         self.assertTrue(status)
     with patch('managesf.model.yamlbkd.engine.'
                'SFResourceBackendEngine._load_resources_data') as l, \
             patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._get_data_diff') as g, \
             patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                   '_resolv_resources_need_refresh') as r, \
             patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._apply_changes') as a:
         l.side_effect = YAMLDBException('')
         eng = SFResourceBackendEngine(path, None)
         status, logs = eng.apply(None, None, None, None)
         self.assertEqual(len(logs), 1)
         self.assertFalse(status)
Пример #15
0
    def test_resolv_resources_need_refresh(self):
        class Master(BaseResource):
            MODEL_TYPE = 'master'
            MODEL = {
                'name': (str, "+*", True, None, True, "desc"),
                'key': (list, "+*", True, None, True, "desc"),
            }
            PRIORITY = 40
            PRIMARY_KEY = None

            def get_deps(self):
                deps = {'dummies': set([])}
                deps['dummies'].add(self.resource['key'])
                return deps

        # Engine dectected dummies:d1 has been updated
        changes = {'dummies': {'update': {'d1': {}}}}

        # masters:m1:key depends on dummies:d1
        tree = {
            'resources': {
                'dummies': {
                    'd1': {
                        'name': 'dummy1',
                        'namespace': 'space',
                    },
                },
                'masters': {
                    'm1': {
                        'key': 'd1',
                    }
                }
            }
        }

        en = SFResourceBackendEngine(None, None)
        with patch.dict(engine.MAPPING,
                        {'dummies': Dummy,
                         'masters': Master}):
            logs = en._resolv_resources_need_refresh(changes, tree)
            self.assertIn('m1', changes['masters']['update'])
            self.assertIn('d1', changes['dummies']['update'])
            self.assertEqual(len(changes['masters']['update']), 1)
            self.assertEqual(len(changes['dummies']['update']), 1)
            self.assertIn('Resource [type: masters, ID: m1] need a '
                          'refresh as at least one of its dependencies '
                          'has been updated', logs)
            self.assertEqual(len(logs), 1)

        # Engine dectected masters:m1 has been updated
        changes = {'masters': {'update': {'m1': {}}}}

        en = SFResourceBackendEngine(None, None)
        with patch.dict(engine.MAPPING,
                        {'dummies': Dummy,
                         'masters': Master}):
            logs = en._resolv_resources_need_refresh(changes, tree)
            # masters:m1 is on top of dependency chain
            # no addtionnal update trigger will be scheduled then
            self.assertEqual(len(logs), 0)
            self.assertIn('m1', changes['masters']['update'])
            self.assertEqual(len(changes['masters']['update']), 1)
            self.assertNotIn('dummies', changes)

        class Master2(BaseResource):
            MODEL_TYPE = 'master2'
            MODEL = {
                'name': (str, "+*", True, None, True, "desc"),
                'key': (str, "+*", True, None, True, "desc"),
            }
            PRIORITY = 30
            PRIMARY_KEY = None

            def get_deps(self):
                return {'masters': set([self.resource['key']])}

        # Engine dectected dummies:d1 has been updated
        changes = {'dummies': {'update': {'d1': {}}}}

        # masters:m1:key depends on dummies:d1
        # masters2:m1:key depends on master:m1
        tree = {
            'resources': {
                'dummies': {
                    'd1': {
                        'name': 'dummy1',
                        'namespace': 'space',
                    },
                },
                'masters': {
                    'm1': {
                        'key': 'd1',
                    }
                },
                'masters2': {
                    'm1': {
                        'key': 'm1',
                    }
                }
            }
        }
        en = SFResourceBackendEngine(None, None)
        with patch.dict(engine.MAPPING,
                        {'dummies': Dummy,
                         'masters': Master,
                         'masters2': Master2}):
            logs = en._resolv_resources_need_refresh(changes, tree)
            self.assertTrue(len(logs), 2)
            self.assertIn('Resource [type: masters, ID: m1] need a refresh '
                          'as at least one of its dependencies has been '
                          'updated', logs)
            self.assertIn('Resource [type: masters2, ID: m1] need a refresh '
                          'as at least one of its dependencies has been '
                          'updated', logs)
            self.assertIn('m1', changes['masters2']['update'])
            self.assertIn('m1', changes['masters']['update'])
            self.assertIn('d1', changes['dummies']['update'])
            self.assertTrue(len(changes['masters2']['update']), 1)
            self.assertTrue(len(changes['masters']['update']), 1)
            self.assertTrue(len(changes['dummies']['update']), 1)
Пример #16
0
 def get_resources(self):
     return SFResourceBackendEngine(
         os.path.join(conf.resources['workdir'], 'read'),
         conf.resources['subdir']).get(conf.resources['master_repo'],
                                       'master')['resources']
Пример #17
0
    def test_direct_apply(self):
        path = tempfile.mkdtemp()
        self.to_delete.append(path)
        with patch('yaml.safe_load'), \
                patch('managesf.model.yamlbkd.yamlbackend.YAMLBackend.'
                      '_validate_base_struct'), \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_get_data_diff') as g, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_deps_constraints') as cd, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_unicity_constraints') as cu, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_validate_changes') as v, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_resolv_resources_need_refresh') as r, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_apply_changes') as a:
            a.return_value = False
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.direct_apply(None, None)
            self.assertTrue(status)
            self.assertEqual(len(logs), 0)
            self.assertTrue(g.called)
            self.assertTrue(cd.called)
            self.assertTrue(cu.called)
            self.assertTrue(v.called)
            self.assertTrue(r.called)
            self.assertTrue(a.called)
            self.assertTrue(status)

        with patch('yaml.safe_load'), \
                patch('managesf.model.yamlbkd.yamlbackend.YAMLBackend.'
                      '_validate_base_struct'), \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_get_data_diff') as g, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_deps_constraints') as cd, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_unicity_constraints') as cu, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_validate_changes') as v, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_resolv_resources_need_refresh') as r, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_apply_changes') as a:
            v.side_effect = ResourceInvalidException('')
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.direct_apply(None, None)
            self.assertFalse(status)
            self.assertEqual(len(logs), 1)
            self.assertTrue(g.called)
            self.assertTrue(cd.called)
            self.assertTrue(cu.called)
            self.assertFalse(r.called)
            self.assertFalse(a.called)
        with patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                   '_apply_changes') as a, \
                patch.dict(engine.MAPPING, {'dummies': Dummy},
                           clear=True):
            a.return_value = False
            prev = "resources: {}"
            new = """resources:
  dummies:
    id1:
      name: dum
      namespace: a
"""
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.direct_apply(prev, new)
            self.assertIn(
                'id1', a.call_args[0][0]['dummies']['create'])
            self.assertEqual(
                len(a.call_args[0][0]['dummies']['update']), 0)
            self.assertEqual(
                len(a.call_args[0][0]['dummies']['delete']), 0)
            self.assertTrue(status)
        with patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                   '_apply_changes') as a, \
                patch.dict(engine.MAPPING, {'dummies': Dummy},
                           clear=True):
            new = "a: True"
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.direct_apply(prev, new)
            self.assertFalse(status)
            self.assertListEqual(
                ['The main resource data structure is invalid'],
                logs)
            self.assertFalse(status)
Пример #18
0
 def test_get_data_diff(self):
     with patch.dict(engine.MAPPING, {'dummies': Dummy}):
         # Test add resource change detected
         prev = {'resources': {'dummies': {}}}
         new = {'resources': {'dummies': {'myprojectid': {
                'namespace': 'sf',
                'name': 'myproject'},
         }}}
         eng = SFResourceBackendEngine(None, None)
         ret = eng._get_data_diff(prev, new)
         self.assertIn('dummies', ret)
         self.assertIn('create', ret['dummies'])
         self.assertIn('myprojectid', ret['dummies']['create'])
         self.assertDictEqual(new['resources']['dummies']['myprojectid'],
                              ret['dummies']['create']['myprojectid'])
         self.assertEqual(len(ret['dummies']['delete'].keys()), 0)
         self.assertEqual(len(ret['dummies']['update'].keys()), 0)
         # Test delete resource change detected
         prev = {'resources': {'dummies': {'myprojectid': {
                 'namespace': 'sf',
                 'name': 'myproject'},
         }}}
         new = {'resources': {'dummies': {}}}
         eng = SFResourceBackendEngine(None, None)
         ret = eng._get_data_diff(prev, new)
         self.assertIn('myprojectid', ret['dummies']['delete'])
         self.assertEqual(len(ret['dummies']['create'].keys()), 0)
         self.assertEqual(len(ret['dummies']['update'].keys()), 0)
         # Test update resource change detected
         prev = {'resources': {'dummies': {'myprojectid': {
                 'namespace': 'sf'},
         }}}
         new = {'resources': {'dummies': {'myprojectid': {
                'namespace': 'sf2'},
         }}}
         path = tempfile.mkdtemp()
         self.to_delete.append(path)
         eng = SFResourceBackendEngine(path, None)
         ret = eng._get_data_diff(prev, new)
         self.assertIn('myprojectid', ret['dummies']['update'])
         self.assertIn(
             'namespace',
             ret['dummies']['update']['myprojectid']['changed'])
         self.assertDictEqual(
             new['resources']['dummies']['myprojectid'],
             ret['dummies']['update']['myprojectid']['data'])
         # Test that multiple resource changes are detected
         prev = {'resources': {
             'dummies': {
                 'myprojectid': {
                     'namespace': 'sf',
                     'name': 'myproject'},
                 'superid': {
                     'namespace': 'super',
                     'name': 'project'}
                 },
             'groups': {}
         }}
         new = {'resources': {
             'dummies': {
                 'myprojectid': {
                     'namespace': 'sfnew',
                     'name': 'mynewproject'},
                 'myproject2id': {
                     'namespace': 'sfnew',
                     'name': 'newproject'}
                 },
             'groups': {
                 'mygroupid': {
                     'name': 'mynewgroup'},
             }
         }}
         eng = SFResourceBackendEngine(None, None)
         ret = eng._get_data_diff(prev, new)
         self.assertDictEqual(ret['dummies']['delete']['superid'],
                              prev['resources']['dummies']['superid'])
         self.assertDictEqual(ret['dummies']['create']['myproject2id'],
                              new['resources']['dummies']['myproject2id'])
         self.assertIn('namespace',
                       ret['dummies']['update']['myprojectid']['changed'])
         self.assertDictEqual(
             ret['dummies']['update']['myprojectid']['data'],
             new['resources']['dummies']['myprojectid'])
         self.assertDictEqual(ret['groups']['create']['mygroupid'],
                              new['resources']['groups']['mygroupid'])
         # Test update resource change detected on a list
         prev = {'resources': {'dummies': {'myprojectid': {
                 'members': ['joe', 'paul']}}}}
         new = {'resources': {'dummies': {'myprojectid': {
                'members': ['paul']}}}}
         path = tempfile.mkdtemp()
         self.to_delete.append(path)
         eng = SFResourceBackendEngine(path, None)
         ret = eng._get_data_diff(prev, new)
         self.assertSetEqual(
             ret['dummies']['update']['myprojectid']['changed'],
             set(['members']))
Пример #19
0
 def test_init_engine(self):
     SFResourceBackendEngine('/tmp/dir',
                             'resources')
Пример #20
0
    def test_get_missing_resources(self):
        class Dummy2(Dummy):
            MODEL_TYPE = 'dummy2'
            MODEL = {
                'name': (
                    str,
                    '.*',
                    True,
                    None,
                    False,
                    "Resource name",
                ),
                'deps': (
                    list,
                    '.*',
                    False,
                    [],
                    True,
                    "Resource dependencies",
                ),
            }
            PRIMARY_KEY = 'name'

            def get_deps(self, keyname=False):
                if keyname:
                    return 'deps'
                else:
                    return {'dummies': set(self.resource['deps'])}

        with patch('managesf.model.yamlbkd.yamlbackend.'
                   'YAMLBackend.__init__'), \
                patch.object(SFResourceBackendEngine, 'get') as g, \
                patch.dict(engine.MAPPING,
                           {'dummies': Dummy, 'dummies2': Dummy2},
                           clear=True), \
                patch('managesf.model.yamlbkd.resources.'
                      'dummy.DummyOps.get_all') as ga:
            eng = SFResourceBackendEngine(None, None)
            # PRIMARY_KEY of Dummy is 'name'
            # PRIMARY_KEY of Dummy2 is 'name'

            # Check basic scenario. dummies:d2 is really new
            current_resources = {
                'dummies': {
                    'd1': {
                        'namespace': 'sf',
                        'name': 'd1',
                    },
                }
            }
            real_resources = {
                'dummies': {
                    'd2': {
                        'namespace': 'sf',
                        'name': 'd2',
                    },
                }
            }
            g.return_value = {'resources': current_resources}
            ga.return_value = ([], real_resources)
            logs, ret = eng.get_missing_resources(None, None)
            expected = {
                'resources': {
                    'dummies': {
                        'd2': {
                            'namespace': 'sf',
                        },
                    }
                }
            }
            self.assertDictEqual(ret, expected)
            self.assertListEqual(logs, [])

            # Check both resources are detected similar.
            # dummies:d1 is dummies:dummy-d1-id
            current_resources = {
                'dummies': {
                    'd1': {
                        'namespace': 'sf',
                    },
                }
            }
            real_resources = {
                'dummies': {
                    'd1': {
                        'namespace': 'sf',
                    },
                }
            }
            g.return_value = {'resources': current_resources}
            ga.return_value = ([], real_resources)
            logs, ret = eng.get_missing_resources(None, None)
            expected = {
                'resources': {}
            }
            self.assertDictEqual(ret, expected)
            self.assertListEqual(logs, [])

            # Check both resources are detected similar.
            # dummies:d1 is dummies:dummy-d1-id
            # dummies2:d2_1 depends on dummies:d1 but
            # dummies:d1 is know under dummies:dummy-d1-id
            # This check make sure the deps if is updated.
            current_resources = {
                'dummies': {
                    'd1': {
                        'namespace': 'sf',
                    },
                }
            }
            real_resources = {
                'dummies': {
                    'd1': {
                        'namespace': 'sf',
                    },
                },
                'dummies2': {
                    'd2_1': {
                        'deps': ['d1'],
                    },
                },
            }
            g.return_value = {'resources': current_resources}
            ga.return_value = ([], real_resources)
            logs, ret = eng.get_missing_resources(None, None)
            expected = {
                'resources': {
                    'dummies2': {
                        'd2_1': {
                            'deps': ['d1'],
                        }
                    }
                }
            }
            self.assertDictEqual(ret, expected)
            self.assertListEqual(logs, [])
Пример #21
0
    def test_apply_changes(self):
        eng = SFResourceBackendEngine(None, None)
        apply_logs = []
        with patch.dict(engine.MAPPING, {'dummies': Dummy}):
            with patch('managesf.model.yamlbkd.resources.'
                       'dummy.DummyOps.create') as c:
                c.return_value = []
                changes = {'dummies': {'create': {'myprojectid': {}}}}
                self.assertFalse(eng._apply_changes(changes, apply_logs, {}))
                self.assertTrue(c.called)
            self.assertIn(
                'Resource [type: dummies, ID: myprojectid] '
                'will be created.',
                apply_logs)
            self.assertIn(
                'Resource [type: dummies, ID: myprojectid] '
                'has been created.',
                apply_logs)
            self.assertTrue(len(apply_logs), 2)

            apply_logs = []
            with patch('managesf.model.yamlbkd.resources.'
                       'dummy.DummyOps.create') as c:
                c.return_value = ["Resource API error"]
                changes = {'dummies': {'create': {'myprojectid': {}}}}
                self.assertTrue(eng._apply_changes(changes, apply_logs, {}))

            apply_logs = []
            with patch('managesf.model.yamlbkd.resources.'
                       'dummy.DummyOps.create') as c:
                c.return_value = ["Resource API error"]
                changes = {
                    'dummies': {
                        'create': {
                            'myprojectid': {}
                        },
                        'update': {
                            'myprojectid2': {
                                'data': {'key': 'value'},
                                'changed': ['key']
                            }
                        }
                    }
                }
                self.assertTrue(eng._apply_changes(changes, apply_logs, {}))
                self.assertIn('Resource [type: dummies, ID: myprojectid] '
                              'will be created.',
                              apply_logs)
                self.assertIn('Resource API error',
                              apply_logs)
                self.assertIn('Resource [type: dummies, ID: myprojectid] '
                              'create op failed.',
                              apply_logs)
                self.assertIn('Resource [type: dummies, ID: myprojectid2] '
                              'will be updated.',
                              apply_logs)
                self.assertIn('Resource [type: dummies, ID: myprojectid2] '
                              'has been updated.',
                              apply_logs)

            # Verify an unexpected exception is properly catched
            apply_logs = []
            with patch('managesf.model.yamlbkd.resources.'
                       'dummy.DummyOps.create') as c:
                c.side_effect = Exception('Random Error msg')
                changes = {'dummies': {'create': {'myprojectid': {}}}}
                self.assertTrue(eng._apply_changes(changes, apply_logs, {}))
                self.assertIn('Resource [type: dummies, ID: myprojectid] '
                              'create op error (Random Error msg).',
                              apply_logs)

            # Verify an unexpected exception does not exit _apply_changes
            apply_logs = []
            with patch('managesf.model.yamlbkd.resources.'
                       'dummy.DummyOps.create') as c:
                c.side_effect = Exception('Random Error msg')
                changes = {
                    'dummies': {
                        'create': {
                            'myprojectid1': {},
                            'myprojectid2': {},
                            'myprojectid3': {},
                        },
                    }
                }
                self.assertTrue(eng._apply_changes(changes, apply_logs, {}))
                for r in ('myprojectid1', 'myprojectid2', 'myprojectid3'):
                    self.assertIn(
                        'Resource [type: dummies, ID: %s] will be created.' % (
                            r), apply_logs)
                    self.assertIn(
                        'Resource [type: dummies, ID: %s] create op error '
                        '(Random Error msg).' % r, apply_logs)
                    self.assertIn(
                        'Resource [type: dummies, ID: %s] create op '
                        'failed.' % r, apply_logs)
Пример #22
0
    def test_validate(self):
        path = tempfile.mkdtemp()
        self.to_delete.append(path)

        with patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._load_resources_data') as l, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_get_data_diff') as g, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_deps_constraints') as c, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_unicity_constraints') as cu, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_validate_changes') as v:
            l.return_value = (None, None)
            eng = SFResourceBackendEngine(path, None)
            status, _ = eng.validate(None, None, None, None)
            self.assertTrue(l.called)
            self.assertTrue(g.called)
            self.assertTrue(c.called)
            self.assertTrue(cu.called)
            self.assertTrue(v.called)
            self.assertTrue(status)

        with patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._load_resources_data') as l, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_get_data_diff') as g, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_deps_constraints') as c, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_unicity_constraints') as cu, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_validate_changes') as v:
            l.side_effect = YAMLDBException('')
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.validate(None, None, None, None)
            self.assertEqual(len(logs), 1)
            self.assertFalse(status)

        with patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._load_resources_data') as l, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_get_data_diff') as g, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_deps_constraints') as c, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_unicity_constraints') as cu, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_validate_changes') as v:
            l.return_value = (None, None)
            v.side_effect = ResourceInvalidException('')
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.validate(None, None, None, None)
            self.assertEqual(len(logs), 1)
            self.assertFalse(status)

        with patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._load_resources_data') as l, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_get_data_diff') as g, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_deps_constraints') as c, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_unicity_constraints') as cu, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_validate_changes') as v:
            l.return_value = (None, None)
            c.side_effect = ResourceDepsException('')
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.validate(None, None, None, None)
            self.assertEqual(len(logs), 1)
            self.assertFalse(status)

        with patch('managesf.model.yamlbkd.engine.'
                   'SFResourceBackendEngine._load_resources_data') as l, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_get_data_diff') as g, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_deps_constraints') as c, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_check_unicity_constraints') as cu, \
                patch('managesf.model.yamlbkd.engine.SFResourceBackendEngine.'
                      '_validate_changes') as v:

            l.return_value = (None, None)
            cu.side_effect = ResourceUnicityException('')
            eng = SFResourceBackendEngine(path, None)
            status, logs = eng.validate(None, None, None, None)
            self.assertEqual(len(logs), 1)
            self.assertFalse(status)