示例#1
0
    def test_network_get(self):
        network_get_out = '''{
  "bind-addresses": [
    {
      "mac-address": "",
      "interface-name": "",
      "addresses": [
        {
          "hostname": "",
          "value": "192.0.2.2",
          "cidr": ""
        }
      ]
    }
  ],
  "egress-subnets": [
    "192.0.2.2/32"
  ],
  "ingress-addresses": [
    "192.0.2.2"
  ]
}'''
        fake_script(
            self, 'network-get',
            f'''[ "$1" = deadbeef ] && echo '{network_get_out}' || exit 1''')
        network_info = self.backend.network_get('deadbeef')
        self.assertEqual(network_info, json.loads(network_get_out))
        self.assertEqual(fake_script_calls(self, clear=True),
                         [['network-get', 'deadbeef', '--format=json']])

        network_info = self.backend.network_get('deadbeef', 1)
        self.assertEqual(network_info, json.loads(network_get_out))
        self.assertEqual(
            fake_script_calls(self, clear=True),
            [['network-get', 'deadbeef', '-r', '1', '--format=json']])
示例#2
0
    def test_storage(self):
        # TODO: (jam) 2020-05-07 Harness doesn't yet expose storage-get issue #263
        meta = ops.charm.CharmMeta()
        meta.storages = {'disks': None, 'data': None}
        model = ops.model.Model('myapp/0', meta, ops.model._ModelBackend())

        fake_script(self, 'storage-list', '''
            if [ "$1" = disks ]; then
                echo '["disks/0", "disks/1"]'
            else
                echo '[]'
            fi
        ''')
        fake_script(self, 'storage-get', '''
            if [ "$2" = disks/0 ]; then
                echo '"/var/srv/disks/0"'
            elif [ "$2" = disks/1 ]; then
                echo '"/var/srv/disks/1"'
            else
                exit 2
            fi
        ''')
        fake_script(self, 'storage-add', '')

        self.assertEqual(len(model.storages), 2)
        self.assertEqual(model.storages.keys(), meta.storages.keys())
        self.assertIn('disks', model.storages)
        test_cases = {
            0: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/0')},
            1: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/1')},
        }
        for storage in model.storages['disks']:
            self.assertEqual(storage.name, 'disks')
            self.assertIn(storage.id, test_cases)
            self.assertEqual(storage.name, test_cases[storage.id]['name'])
            self.assertEqual(storage.location, test_cases[storage.id]['location'])

        self.assertEqual(fake_script_calls(self, clear=True), [
            ['storage-list', 'disks', '--format=json'],
            ['storage-get', '-s', 'disks/0', 'location', '--format=json'],
            ['storage-get', '-s', 'disks/1', 'location', '--format=json'],
        ])

        self.assertSequenceEqual(model.storages['data'], [])
        model.storages.request('data', count=3)
        self.assertEqual(fake_script_calls(self), [
            ['storage-list', 'data', '--format=json'],
            ['storage-add', 'data=3'],
        ])

        # Try to add storage not present in charm metadata.
        with self.assertRaises(ops.model.ModelError):
            model.storages.request('deadbeef')

        # Invalid count parameter types.
        for count_v in [None, False, 2.0, 'a', b'beef', object]:
            with self.assertRaises(TypeError):
                model.storages.request('data', count_v)
示例#3
0
    def test_juju_log(self):
        fake_script(self, 'juju-log', 'exit 0')
        self.backend.juju_log('WARNING', 'foo')
        self.assertEqual(fake_script_calls(self, clear=True),
                         [['juju-log', '--log-level', 'WARNING', 'foo']])

        with self.assertRaises(TypeError):
            self.backend.juju_log('DEBUG')
        self.assertEqual(fake_script_calls(self, clear=True), [])

        fake_script(self, 'juju-log', 'exit 1')
        with self.assertRaises(ops.model.ModelError):
            self.backend.juju_log('BAR', 'foo')
        self.assertEqual(fake_script_calls(self, clear=True),
                         [['juju-log', '--log-level', 'BAR', 'foo']])
示例#4
0
 def test_action_get_error(self):
     fake_script(self, 'action-get', '')
     fake_script(self, 'action-get', f'echo fooerror >&2 ; exit 1')
     with self.assertRaises(ops.model.ModelError):
         self.backend.action_get()
     calls = [['action-get', '--format=json']]
     self.assertEqual(fake_script_calls(self, clear=True), calls)
示例#5
0
    def test_relation_set_fail(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db2 ] && echo '["db2:5"]' || echo '[]'""")
        fake_script(self, 'relation-list',
                    """[ "$2" = 5 ] && echo '["remoteapp1/0"]' || exit 2""")
        fake_script(
            self, 'relation-get',
            """([ "$2" = 5 ] && [ "$4" = "myapp/0" ]) && echo '{"host": "myapp-0"}' || exit 2"""
        )
        fake_script(self, 'relation-set', 'exit 2')

        rel_db2 = self.model.relations['db2'][0]
        # Force memory cache to be loaded.
        self.assertIn('host', rel_db2.data[self.model.unit])
        with self.assertRaises(ops.model.ModelError):
            rel_db2.data[self.model.unit]['host'] = 'bar'
        self.assertEqual(rel_db2.data[self.model.unit]['host'], 'myapp-0')
        with self.assertRaises(ops.model.ModelError):
            del rel_db2.data[self.model.unit]['host']
        self.assertIn('host', rel_db2.data[self.model.unit])

        self.assertEqual(
            fake_script_calls(self),
            [['relation-ids', 'db2', '--format=json'],
             ['relation-list', '-r', '5', '--format=json'],
             [
                 'relation-get', '-r', '5', '-', 'myapp/0', '--app=False',
                 '--format=json'
             ], ['relation-set', '-r', '5', 'host=bar', '--app=False'],
             ['relation-set', '-r', '5', 'host=', '--app=False']])
示例#6
0
    def test_unit_relation_data(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")
        fake_script(self, 'relation-list',
                    """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""")
        fake_script(
            self, 'relation-get',
            """([ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]) && echo '{"host": "remoteapp1-0"}' || exit 2"""
        )

        random_unit = self.model._cache.get(ops.model.Unit, 'randomunit/0')
        with self.assertRaises(KeyError):
            self.model.get_relation('db1').data[random_unit]
        remoteapp1_0 = next(
            filter(lambda u: u.name == 'remoteapp1/0',
                   self.model.get_relation('db1').units))
        self.assertEqual(
            self.model.get_relation('db1').data[remoteapp1_0],
            {'host': 'remoteapp1-0'})

        self.assertEqual(fake_script_calls(self),
                         [['relation-ids', 'db1', '--format=json'],
                          ['relation-list', '-r', '4', '--format=json'],
                          [
                              'relation-get', '-r', '4', '-', 'remoteapp1/0',
                              '--app=False', '--format=json'
                          ]])
示例#7
0
 def test_action_set_error(self):
     fake_script(self, 'action-get', '')
     fake_script(self, 'action-set', f'echo fooerror >&2 ; exit 1')
     with self.assertRaises(ops.model.ModelError):
         self.backend.action_set({'foo': 'bar', 'dead': 'beef cafe'})
     calls = [["action-set", "foo=bar", "dead=beef cafe"]]
     self.assertEqual(fake_script_calls(self, clear=True), calls)
示例#8
0
 def test_application_version_set_invalid(self):
     fake_script(self, 'application-version-set', 'exit 0')
     with self.assertRaises(TypeError):
         self.backend.application_version_set(2)
     with self.assertRaises(TypeError):
         self.backend.application_version_set()
     self.assertEqual(fake_script_calls(self), [])
示例#9
0
    def test_relation_data_modify_remote(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")
        fake_script(self, 'relation-list',
                    """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""")
        fake_script(
            self, 'relation-get',
            """([ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]) && echo '{"host": "remoteapp1-0"}' || exit 2"""
        )

        rel_db1 = self.model.get_relation('db1')
        remoteapp1_0 = next(
            filter(lambda u: u.name == 'remoteapp1/0',
                   self.model.get_relation('db1').units))
        # Force memory cache to be loaded.
        self.assertIn('host', rel_db1.data[remoteapp1_0])
        with self.assertRaises(ops.model.RelationDataError):
            rel_db1.data[remoteapp1_0]['foo'] = 'bar'
        self.assertNotIn('foo', rel_db1.data[remoteapp1_0])

        self.assertEqual(fake_script_calls(self),
                         [['relation-ids', 'db1', '--format=json'],
                          ['relation-list', '-r', '4', '--format=json'],
                          [
                              'relation-get', '-r', '4', '-', 'remoteapp1/0',
                              '--app=False', '--format=json'
                          ]])
示例#10
0
    def test_network_get_errors(self):
        err_no_endpoint = 'ERROR no network config found for binding "$2"'
        err_no_rel = 'ERROR invalid value "$3" for option -r: relation not found'

        test_cases = [
            (
                lambda: fake_script(self, 'network-get',
                                    f'echo {err_no_endpoint} >&2 ; exit 1'),
                lambda: self.backend.network_get("deadbeef"),
                ops.model.ModelError,
                [['network-get', 'deadbeef', '--format=json']],
            ),
            (
                lambda: fake_script(self, 'network-get',
                                    f'echo {err_no_rel} >&2 ; exit 2'),
                lambda: self.backend.network_get("deadbeef", 3),
                ops.model.RelationNotFoundError,
                [['network-get', 'deadbeef', '-r', '3', '--format=json']],
            )
        ]
        for do_fake, run, exception, calls in test_cases:
            do_fake()
            with self.assertRaises(exception):
                run()
            self.assertEqual(fake_script_calls(self, clear=True), calls)
示例#11
0
    def test_app_relation_data_modify_local_as_minion(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")
        fake_script(
            self, 'relation-list',
            """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2"""
        )
        fake_script(
            self, 'relation-get',
            """[ "$2" = 4 ] && [ "$4" = myapp ] && echo '{"password": "******"}' || exit 2"""
        )
        fake_script(self, 'is-leader', 'echo false')

        local_app = self.model.unit.app

        rel_db1 = self.model.get_relation('db1')
        self.assertEqual(rel_db1.data[local_app], {'password': '******'})

        with self.assertRaises(ops.model.RelationDataError):
            rel_db1.data[local_app]['password'] = '******'

        self.assertEqual(fake_script_calls(self), [
            ['relation-ids', 'db1', '--format=json'],
            ['relation-list', '-r', '4', '--format=json'],
            [
                'relation-get', '-r', '4', '-', 'myapp', '--app=True',
                '--format=json'
            ],
            ['is-leader', '--format=json'],
        ])
示例#12
0
 def test_storage_tool_errors(self):
     test_cases = [(
         lambda: fake_script(self, 'storage-list', 'echo fooerror >&2 ; exit 1'),
         lambda: self.backend.storage_list('foobar'),
         ops.model.ModelError,
         [['storage-list', 'foobar', '--format=json']],
     ), (
         lambda: fake_script(self, 'storage-get', 'echo fooerror >&2 ; exit 1'),
         lambda: self.backend.storage_get('foobar', 'someattr'),
         ops.model.ModelError,
         [['storage-get', '-s', 'foobar', 'someattr', '--format=json']],
     ), (
         lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'),
         lambda: self.backend.storage_add('foobar', count=2),
         ops.model.ModelError,
         [['storage-add', 'foobar=2']],
     ), (
         lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'),
         lambda: self.backend.storage_add('foobar', count=object),
         TypeError,
         [],
     ), (
         lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'),
         lambda: self.backend.storage_add('foobar', count=True),
         TypeError,
         [],
     )]
     for do_fake, run, exception, calls in test_cases:
         do_fake()
         with self.assertRaises(exception):
             run()
         self.assertEqual(fake_script_calls(self, clear=True), calls)
示例#13
0
    def test_relation_data_del_key(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")
        fake_script(self, 'relation-list',
                    """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""")
        fake_script(self, 'relation-set',
                    '''[ "$2" = 4 ] && exit 0 || exit 2''')
        fake_script(
            self, 'relation-get',
            """([ "$2" = 4 ] && [ "$4" = "myapp/0" ]) && echo '{"host": "bar"}' || exit 2"""
        )

        rel_db1 = self.model.get_relation('db1')
        # Force memory cache to be loaded.
        self.assertIn('host', rel_db1.data[self.model.unit])
        del rel_db1.data[self.model.unit]['host']
        fake_script(
            self, 'relation-get',
            """([ "$2" = 4 ] && [ "$4" = "myapp/0" ]) && echo '{}' || exit 2"""
        )
        self.assertNotIn('host', rel_db1.data[self.model.unit])

        self.assertEqual(
            fake_script_calls(self),
            [['relation-ids', 'db1', '--format=json'],
             ['relation-list', '-r', '4', '--format=json'],
             [
                 'relation-get', '-r', '4', '-', 'myapp/0', '--app=False',
                 '--format=json'
             ], ['relation-set', '-r', '4', 'host=', '--app=False']])
示例#14
0
    def test_remote_app_status(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")
        fake_script(
            self, 'relation-list',
            """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2"""
        )

        remoteapp1 = self.model.get_relation('db1').app

        # Remote application status is always unknown.
        self.assertIsInstance(remoteapp1.status, ops.model.UnknownStatus)

        test_statuses = (
            ops.model.UnknownStatus(),
            ops.model.ActiveStatus(),
            ops.model.MaintenanceStatus('Upgrading software'),
            ops.model.BlockedStatus('Awaiting manual resolution'),
            ops.model.WaitingStatus('Awaiting related app updates'),
        )
        for target_status in test_statuses:
            with self.assertRaises(RuntimeError):
                remoteapp1.status = target_status

        self.assertEqual(fake_script_calls(self, clear=True), [
            ['relation-ids', 'db1', '--format=json'],
            ['relation-list', '-r', '4', '--format=json'],
        ])
示例#15
0
    def test_remote_app_relation_data(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")
        fake_script(
            self, 'relation-list',
            """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2"""
        )
        fake_script(
            self, 'relation-get',
            """[ "$2" = 4 ] && [ "$4" = remoteapp1 ] && echo '{"secret": "cafedeadbeef"}' || exit 2"""
        )

        # Try to get relation data for an invalid remote application.
        random_app = self.model._cache.get(ops.model.Application, 'randomapp')
        with self.assertRaises(KeyError):
            self.model.get_relation('db1').data[random_app]

        remoteapp1 = self.model.get_relation('db1').app
        self.assertEqual(
            self.model.get_relation('db1').data[remoteapp1],
            {'secret': 'cafedeadbeef'})

        self.assertEqual(fake_script_calls(self), [
            ['relation-ids', 'db1', '--format=json'],
            ['relation-list', '-r', '4', '--format=json'],
            [
                'relation-get', '-r', '4', '-', 'remoteapp1', '--app=True',
                '--format=json'
            ],
        ])
示例#16
0
 def test_action_log_error(self):
     fake_script(self, 'action-get', '')
     fake_script(self, 'action-log', f'echo fooerror >&2 ; exit 1')
     with self.assertRaises(ops.model.ModelError):
         self.backend.action_log('log-message')
     calls = [["action-log", "log-message"]]
     self.assertEqual(fake_script_calls(self, clear=True), calls)
示例#17
0
 def test_action_get(self):
     fake_script(self, 'action-get',
                 """echo '{"foo-name": "bar", "silent": false}'""")
     params = self.backend.action_get()
     self.assertEqual(params['foo-name'], 'bar')
     self.assertEqual(params['silent'], False)
     self.assertEqual(fake_script_calls(self),
                      [['action-get', '--format=json']])
示例#18
0
    def test_pod_spec(self):
        # TODO: (jam) 2020-05-07 Harness doesn't yet expose pod-spec-set issue #261
        meta = ops.charm.CharmMeta.from_yaml('''
            name: myapp
        ''')
        model = ops.model.Model('myapp/0', meta, ops.model._ModelBackend())
        fake_script(self, 'pod-spec-set', """
                    cat $2 > $(dirname $0)/spec.json
                    [[ -n $4 ]] && cat $4 > $(dirname $0)/k8s_res.json || true
                    """)
        fake_script(self, 'is-leader', 'echo true')
        spec_path = self.fake_script_path / 'spec.json'
        k8s_res_path = self.fake_script_path / 'k8s_res.json'

        def check_calls(calls):
            # There may 1 or 2 calls because of is-leader.
            self.assertLessEqual(len(fake_calls), 2)
            pod_spec_call = next(filter(lambda c: c[0] == 'pod-spec-set', calls))
            self.assertEqual(pod_spec_call[:2], ['pod-spec-set', '--file'])

            # 8 bytes are used as of python 3.4.0, see Python bug #12015.
            # Other characters are from POSIX 3.282 (Portable Filename
            # Character Set) a subset of which Python's mkdtemp uses.
            self.assertRegex(pod_spec_call[2], '.*/tmp[A-Za-z0-9._-]{8}-pod-spec-set')

        model.pod.set_spec({'foo': 'bar'})
        self.assertEqual(spec_path.read_text(), '{"foo": "bar"}')
        self.assertFalse(k8s_res_path.exists())

        fake_calls = fake_script_calls(self, clear=True)
        check_calls(fake_calls)

        model.pod.set_spec({'bar': 'foo'}, {'qux': 'baz'})
        self.assertEqual(spec_path.read_text(), '{"bar": "foo"}')
        self.assertEqual(k8s_res_path.read_text(), '{"qux": "baz"}')

        fake_calls = fake_script_calls(self, clear=True)
        check_calls(fake_calls)

        # Create a new model to drop is-leader caching result.
        self.backend = ops.model._ModelBackend()
        meta = ops.charm.CharmMeta()
        model = ops.model.Model('myapp/0', meta, self.backend)
        fake_script(self, 'is-leader', 'echo false')
        with self.assertRaises(ops.model.ModelError):
            model.pod.set_spec({'foo': 'bar'})
示例#19
0
    def test_binding_by_relation_name(self):
        fake_script(self, 'network-get',
                    '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out))
        binding_name = 'db0'
        expected_calls = [['network-get', 'db0', '--format=json']]

        binding = self.model.get_binding(binding_name)
        self._check_binding_data(binding_name, binding)
        self.assertEqual(fake_script_calls(self, clear=True), expected_calls)
示例#20
0
    def test_local_set_invalid_status(self):
        fake_script(self, 'status-set', 'exit 1')
        fake_script(self, 'is-leader', 'echo true')

        with self.assertRaises(ops.model.ModelError):
            self.model.unit.status = ops.model.UnknownStatus()

        self.assertEqual(fake_script_calls(self, True), [
            ['status-set', '--application=False', 'unknown', ''],
        ])

        with self.assertRaises(ops.model.ModelError):
            self.model.app.status = ops.model.UnknownStatus()

        # A leadership check is needed for application status.
        self.assertEqual(fake_script_calls(self, True), [
            ['is-leader', '--format=json'],
            ['status-set', '--application=True', 'unknown', ''],
        ])
示例#21
0
    def test_is_leader(self):
        def check_remote_units():
            fake_script(self, 'relation-ids',
                        """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")

            fake_script(
                self, 'relation-list',
                """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2"""
            )

            # Cannot determine leadership for remote units.
            for u in self.model.get_relation('db1').units:
                with self.assertRaises(RuntimeError):
                    u.is_leader()

        fake_script(self, 'is-leader', 'echo true')
        self.assertTrue(self.model.unit.is_leader())

        check_remote_units()

        # Create a new model and backend to drop a cached is-leader output.
        self.backend = ops.model.ModelBackend()
        meta = ops.charm.CharmMeta()
        meta.relations = {
            'db0':
            RelationMeta('provides', 'db0', {
                'interface': 'db0',
                'scope': 'global'
            }),
            'db1':
            RelationMeta('requires', 'db1', {
                'interface': 'db1',
                'scope': 'global'
            }),
            'db2':
            RelationMeta('peers', 'db2', {
                'interface': 'db2',
                'scope': 'global'
            }),
        }
        self.model = ops.model.Model('myapp/0', meta, self.backend)

        fake_script(self, 'is-leader', 'echo false')
        self.assertFalse(self.model.unit.is_leader())

        check_remote_units()

        self.assertEqual(fake_script_calls(self), [
            ['is-leader', '--format=json'],
            ['relation-ids', 'db1', '--format=json'],
            ['relation-list', '-r', '4', '--format=json'],
            ['is-leader', '--format=json'],
            ['relation-ids', 'db1', '--format=json'],
            ['relation-list', '-r', '4', '--format=json'],
        ])
示例#22
0
 def test_get(self):
     fake_script(self, 'state-get',
                 dedent("""
         echo 'foo: "bar"'
         """))
     backend = storage._JujuStorageBackend()
     value = backend.get('key')
     self.assertEqual(value, {'foo': 'bar'})
     self.assertEqual(fake_script_calls(self, clear=True), [
         ['state-get', 'key'],
     ])
示例#23
0
    def test_local_set_valid_unit_status(self):
        test_cases = [
            (
                ops.model.ActiveStatus('Green'),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertEqual(fake_script_calls(self, True), [[
                    'status-set', '--application=False', 'active', 'Green'
                ]]),
            ),
            (
                ops.model.MaintenanceStatus('Yellow'),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertEqual(fake_script_calls(self, True), [[
                    'status-set', '--application=False', 'maintenance',
                    'Yellow'
                ]]),
            ),
            (
                ops.model.BlockedStatus('Red'),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertEqual(fake_script_calls(self, True), [[
                    'status-set', '--application=False', 'blocked', 'Red'
                ]]),
            ),
            (
                ops.model.WaitingStatus('White'),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertEqual(fake_script_calls(self, True), [[
                    'status-set', '--application=False', 'waiting', 'White'
                ]]),
            )
        ]

        for target_status, setup_tools, check_tool_calls in test_cases:
            setup_tools()

            self.model.unit.status = target_status

            self.assertEqual(self.model.unit.status, target_status)

            check_tool_calls()
示例#24
0
    def test_local_set_valid_app_status(self):
        fake_script(self, 'is-leader', 'echo true')
        test_cases = [
            (
                ops.model.ActiveStatus(),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertIn([
                    'status-set', '--application=True', 'active', ''
                ], fake_script_calls(self, True)),
            ),
            (
                ops.model.MaintenanceStatus('Yellow'),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertIn([
                    'status-set', '--application=True', 'maintenance', 'Yellow'
                ], fake_script_calls(self, True)),
            ),
            (
                ops.model.BlockedStatus('Red'),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertIn([
                    'status-set', '--application=True', 'blocked', 'Red'
                ], fake_script_calls(self, True)),
            ),
            (
                ops.model.WaitingStatus('White'),
                lambda: fake_script(self, 'status-set', 'exit 0'),
                lambda: self.assertIn([
                    'status-set', '--application=True', 'waiting', 'White'
                ], fake_script_calls(self, True)),
            )
        ]

        for target_status, setup_tools, check_tool_calls in test_cases:
            setup_tools()

            self.model.app.status = target_status

            self.assertEqual(self.model.app.status, target_status)

            check_tool_calls()
示例#25
0
 def test_binding_by_relation(self):
     fake_script(self, 'network-get',
                 '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out))
     binding_name = 'db0'
     expected_calls = [
         ['relation-ids', 'db0', '--format=json'],
         # The two invocations below are due to the get_relation call.
         ['relation-list', '-r', '4', '--format=json'],
         ['network-get', 'db0', '-r', '4', '--format=json'],
     ]
     binding = self.model.get_binding(self.model.get_relation(binding_name))
     self._check_binding_data(binding_name, binding)
     self.assertEqual(fake_script_calls(self, clear=True), expected_calls)
示例#26
0
    def test_config(self):
        fake_script(self, 'config-get',
                    """echo '{"foo":"foo","bar":1,"qux":true}'""")
        self.assertEqual(self.model.config, {
            'foo': 'foo',
            'bar': 1,
            'qux': True,
        })
        with self.assertRaises(TypeError):
            # Confirm that we cannot modify config values.
            self.model.config['foo'] = 'bar'

        self.assertEqual(fake_script_calls(self),
                         [['config-get', '--format=json']])
示例#27
0
    def test_remote_units_is_our(self):
        fake_script(self, 'relation-ids',
                    """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""")
        fake_script(
            self, 'relation-list',
            """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2"""
        )

        for u in self.model.get_relation('db1').units:
            self.assertFalse(u._is_our_unit)
            self.assertFalse(u.app._is_our_app)

        self.assertEqual(fake_script_calls(self),
                         [['relation-ids', 'db1', '--format=json'],
                          ['relation-list', '-r', '4', '--format=json']])
示例#28
0
 def test_valid_metrics(self):
     fake_script(self, 'add-metric', 'exit 0')
     test_cases = [(
         OrderedDict([('foo', 42), ('b-ar', 4.5), ('ba_-z', 4.5), ('a', 1)]),
         OrderedDict([('de', 'ad'), ('be', 'ef_ -')]),
         [['add-metric', '--labels', 'de=ad,be=ef_ -',
           'foo=42', 'b-ar=4.5', 'ba_-z=4.5', 'a=1']]
     ), (
         OrderedDict([('foo1', 0), ('b2r', 4.5)]),
         OrderedDict([('d3', 'aд'), ('b33f', '3_ -')]),
         [['add-metric', '--labels', 'd3=aд,b33f=3_ -', 'foo1=0', 'b2r=4.5']],
     )]
     for metrics, labels, expected_calls in test_cases:
         self.backend.add_metrics(metrics, labels)
         self.assertEqual(fake_script_calls(self, clear=True), expected_calls)
示例#29
0
    def test_local_set_invalid_status(self):
        # juju return exit code 1 if you ask to set status to 'unknown'
        meta = ops.charm.CharmMeta.from_yaml('''
            name: myapp
        ''')
        model = ops.model.Model('myapp/0', meta, self.backend)
        fake_script(self, 'status-set', 'exit 1')
        fake_script(self, 'is-leader', 'echo true')

        with self.assertRaises(ops.model.ModelError):
            model.unit.status = ops.model.UnknownStatus()

        self.assertEqual(fake_script_calls(self, True), [
            ['status-set', '--application=False', 'unknown', ''],
        ])

        with self.assertRaises(ops.model.ModelError):
            model.app.status = ops.model.UnknownStatus()

        # A leadership check is needed for application status.
        self.assertEqual(fake_script_calls(self, True), [
            ['is-leader', '--format=json'],
            ['status-set', '--application=True', 'unknown', ''],
        ])
示例#30
0
    def test_relations_keys(self):
        fake_script(
            self, 'relation-ids',
            """[ "$1" = db2 ] && echo '["db2:5", "db2:6"]' || echo '[]'""")
        fake_script(
            self, 'relation-list',
            """([ "$2" = 5 ] && echo '["remoteapp1/0", "remoteapp1/1"]') || ([ "$2" = 6 ] && echo '["remoteapp2/0"]') || exit 2"""
        )

        for relation in self.model.relations['db2']:
            self.assertIn(self.model.unit, relation.data)
            unit_from_rel = next(
                filter(lambda u: u.name == 'myapp/0', relation.data.keys()))
            self.assertIs(self.model.unit, unit_from_rel)

        self.assertEqual(fake_script_calls(self),
                         [['relation-ids', 'db2', '--format=json'],
                          ['relation-list', '-r', '5', '--format=json'],
                          ['relation-list', '-r', '6', '--format=json']])