def test_remove_uuid_does_not_exist(cartridge_cmd,
                                    clusterwide_conf_non_existent_instance,
                                    tmpdir):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    clusterwide_conf = clusterwide_conf_non_existent_instance

    instances = ['instance-1', 'instance-2']
    write_instances_topology_conf(data_dir, APPNAME, clusterwide_conf.conf,
                                  instances)

    cmd = [
        cartridge_cmd,
        'repair',
        'remove-instance',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        clusterwide_conf.instance_uuid,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 1

    assert_for_instances_group(
        get_logs(output), instances,
        lambda line: "Instance %s isn't found in cluster" % clusterwide_conf.
        instance_uuid in line)
Ejemplo n.º 2
0
def test_non_bootstrapped_instance(cartridge_cmd, clusterwide_conf_simple,
                                   repair_cmd, tmpdir):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    config = clusterwide_conf_simple

    if repair_cmd == 'set-advertise-uri':
        args = [config.instance_uuid, config.instance_uri]
    elif repair_cmd == 'remove-instance':
        args = [config.instance_uuid]
    elif repair_cmd == 'set-leader':
        args = [config.replicaset_uuid, config.instance_uuid]

    cmd = [
        cartridge_cmd,
        'repair',
        repair_cmd,
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
    ]
    cmd.extend(args)

    instances = ['instance-1', 'instance-2']

    # no cluster-wide configs

    # # create empty work dirs for instance-2
    for instance in instances:
        work_dir = os.path.join(data_dir, '%s.%s' % (APPNAME, instance))
        os.makedirs(work_dir)

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 1
    assert "No cluster-wide configs found in %s" % data_dir in output

    # write config for instance-1
    write_instances_topology_conf(data_dir, APPNAME,
                                  clusterwide_conf_simple.conf, instances[:1])

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    if repair_cmd == 'set-advertise-uri':
        first_log_line = "Set %s advertise URI to %s" % (args[0], args[1])
    elif repair_cmd == 'remove-instance':
        first_log_line = "Remove instance with UUID %s" % args[0]
    elif repair_cmd == 'set-leader':
        first_log_line = "Set %s leader to %s" % (args[0], args[1])

    logs = get_logs(output)
    assert len(logs) == 6
    assert logs[0] == first_log_line
    assert logs[1] == "Process application cluster-wide configurations..."
    assert logs[2] == "%s... OK" % instances[0]
    assert logs[3] == "Write application cluster-wide configurations..."
    assert logs[4] == "To reload cluster-wide configurations use --reload flag"
    assert logs[5] == "%s... OK" % instances[0]
def test_bad_args(cartridge_cmd, conf_type, tmpdir,
                  clusterwide_conf_non_existent_instance,
                  clusterwide_conf_srv_expelled):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    configs = {
        'non-existent-srv': clusterwide_conf_non_existent_instance,
        'srv-expelled': clusterwide_conf_srv_expelled,
    }

    config = configs[conf_type]

    instances = ['instance-1', 'instance-2']
    write_instances_topology_conf(data_dir, APPNAME, config.conf, instances)

    cmd = [
        cartridge_cmd, 'repair', 'set-advertise-uri', '--name', APPNAME,
        '--data-dir', data_dir, config.instance_uuid, 'new-uri:666'
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 1

    exp_errors = {
        'non-existent-srv':
        "Instance %s isn't found in cluster" % config.instance_uuid,
        'srv-expelled': "Instance %s is expelled" % config.instance_uuid,
    }

    exp_error = exp_errors[conf_type]
    assert_for_instances_group(get_logs(output), instances,
                               lambda line: exp_error in line)
Ejemplo n.º 4
0
def test_repiar_no_workdirs(cartridge_cmd, clusterwide_conf_simple, repair_cmd,
                            tmpdir):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    args = simple_args.get(repair_cmd, [])

    cmd = [
        cartridge_cmd,
        'repair',
        repair_cmd,
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
    ]

    cmd.extend(args)

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 1
    assert "No instance working directories found in %s" % data_dir in output

    # create other app workdirs
    instances = ['instance-1', 'instance-2']
    write_instances_topology_conf(data_dir, OTHER_APP_NAME,
                                  clusterwide_conf_simple.conf, instances)

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 1
    assert "No instance working directories found in %s" % data_dir in output
def test_set_uri(cartridge_cmd, conf_type, tmpdir, clusterwide_conf_simple,
                 clusterwide_conf_srv_disabled, clusterwide_conf_one_file):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    NEW_URI = 'new-uri:666'

    configs = {
        'simple': clusterwide_conf_simple,
        'srv-disabled': clusterwide_conf_srv_disabled,
        'one-file-config': clusterwide_conf_one_file,
    }

    config = configs[conf_type]
    old_conf = config.conf

    # create app configs
    instances = ['instance-1', 'instance-2']
    conf_paths = write_instances_topology_conf(data_dir, APPNAME, old_conf,
                                               instances, config.one_file)

    # create other app configs
    other_instances = ['other-instance-1', 'other-instance-2']
    other_app_conf_paths = write_instances_topology_conf(
        data_dir,
        OTHER_APP_NAME,
        old_conf,
        other_instances,
        config.one_file,
    )

    cmd = [
        cartridge_cmd,
        'repair',
        'set-advertise-uri',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        config.instance_uuid,
        NEW_URI,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    # check logs
    logs = get_logs(output)
    assert logs[0] == "Set %s advertise URI to %s" % (config.instance_uuid,
                                                      NEW_URI)

    instances_logs = logs[-len(instances):]
    assert_ok_for_all_instances(instances_logs, instances)

    # check app config changes
    new_conf = get_conf_with_new_uri(old_conf, config.instance_uuid, NEW_URI)
    assert_conf_changed(conf_paths, other_app_conf_paths, old_conf, new_conf)
def test_bad_args(cartridge_cmd, conf_type, tmpdir,
                  clusterwide_conf_non_existent_instance,
                  clusterwide_conf_non_existent_rpl,
                  clusterwide_conf_srv_disabled, clusterwide_conf_srv_expelled,
                  clusterwide_conf_srv_from_other_rpl):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    configs = {
        'non-existent-srv': clusterwide_conf_non_existent_instance,
        'non-existent-rpl': clusterwide_conf_non_existent_rpl,
        'srv-disabled': clusterwide_conf_srv_disabled,
        'srv-expelled': clusterwide_conf_srv_expelled,
        'srv-from-other-rpl': clusterwide_conf_srv_from_other_rpl,
    }

    config = configs[conf_type]

    instances = ['instance-1', 'instance-2']
    write_instances_topology_conf(data_dir, APPNAME, config.conf, instances)

    cmd = [
        cartridge_cmd,
        'repair',
        'set-leader',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        config.replicaset_uuid,
        config.instance_uuid,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 1

    exp_errors = {
        'non-existent-srv':
        "Instance %s isn't found in cluster" % config.instance_uuid,
        'non-existent-rpl':
        "Replicaset %s isn't found in the cluster" % config.replicaset_uuid,
        'srv-disabled':
        "Instance %s is disabled" % config.instance_uuid,
        'srv-expelled':
        "Instance %s is expelled" % config.instance_uuid,
        'srv-from-other-rpl':
        "Instance %s doesn't belong to replicaset %s" %
        (config.instance_uuid, config.replicaset_uuid),
    }

    exp_error = exp_errors[conf_type]
    assert_for_instances_group(get_logs(output), instances,
                               lambda line: exp_error in line)
def test_no_force(cartridge_cmd, repair_cmd, tmpdir,
                  clusterwide_conf_simple_v1, clusterwide_conf_simple_v2):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    config1 = clusterwide_conf_simple_v1
    config2 = clusterwide_conf_simple_v2

    # create app configs
    conf1_instances = ['instance-1', 'instance-2']
    write_instances_topology_conf(data_dir, APPNAME, config1.conf,
                                  conf1_instances)

    conf2_instances = ['instance-3', 'instance-4']
    write_instances_topology_conf(data_dir, APPNAME, config2.conf,
                                  conf2_instances)

    args = simple_args.get(repair_cmd, [])
    cmd = [
        cartridge_cmd,
        'repair',
        repair_cmd,
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
    ]

    cmd.extend(args)

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 1

    assert "Clusterwide config is diverged between instances" in output
    assert '''--- instance-3, instance-4
+++ instance-1, instance-2
@@ -27,10 +27,6 @@
     uri: srv-2-uri
   srv-3:
     disabled: false
     replicaset_uuid: rpl-2
     uri: srv-3-uri
-  srv-4:
-    disabled: false
-    replicaset_uuid: rpl-2
-    uri: srv-4-uri
''' in output
def test_set_uri_dry_run(cartridge_cmd, conf_type, tmpdir,
                         clusterwide_conf_simple,
                         clusterwide_conf_srv_disabled):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    NEW_URI = 'new-uri:666'

    configs = {
        'simple': clusterwide_conf_simple,
        'srv-disabled': clusterwide_conf_srv_disabled,
    }

    config = configs[conf_type]
    old_conf = config.conf

    # create app working directories
    instances = ['instance-1', 'instance-2']
    conf_paths = write_instances_topology_conf(data_dir, APPNAME, old_conf,
                                               instances)

    cmd = [
        cartridge_cmd,
        'repair',
        'set-advertise-uri',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        '--dry-run',
        config.instance_uuid,
        NEW_URI,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    # check logs
    assert "Set %s advertise URI to %s" % (config.instance_uuid,
                                           NEW_URI) in output

    exp_diff = '\n'.join([
        '-    uri: %s' % config.instance_uri,
        '+    uri: %s' % NEW_URI,
    ])
    assert exp_diff in output

    # check config wasn't changed
    assert_conf_not_changed(conf_paths, old_conf)
def test_remove(
        cartridge_cmd, conf_type, tmpdir, clusterwide_conf_simple,
        clusterwide_conf_srv_disabled, clusterwide_conf_srv_expelled,
        clusterwide_conf_srv_not_in_leaders, clusterwide_conf_non_existent_rpl,
        clusterwide_conf_srv_last_in_rpl, clusterwide_conf_srv_last_in_leaders,
        clusterwide_conf_current_leader_is_string, clusterwide_conf_one_file):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    configs = {
        'simple': clusterwide_conf_simple,
        'disabled': clusterwide_conf_srv_disabled,
        'expelled': clusterwide_conf_srv_expelled,
        'not-in-leaders': clusterwide_conf_srv_not_in_leaders,
        'non-existent-rpl': clusterwide_conf_non_existent_rpl,
        'srv-last-in-rpl': clusterwide_conf_srv_last_in_rpl,
        'srv-last-in-leaders': clusterwide_conf_srv_last_in_leaders,
        'leader-is-string': clusterwide_conf_current_leader_is_string,
        'one-file-config': clusterwide_conf_one_file,
    }

    config = configs[conf_type]
    old_conf = copy.deepcopy(config.conf)
    instance_uuid = config.instance_uuid

    # create app configs
    instances = ['instance-1', 'instance-2']
    conf_paths = write_instances_topology_conf(data_dir, APPNAME, old_conf,
                                               instances, config.one_file)

    # create other app configs
    other_instances = ['other-instance-1', 'other-instance-2']
    other_app_conf_paths = write_instances_topology_conf(
        data_dir,
        OTHER_APP_NAME,
        old_conf,
        other_instances,
        config.one_file,
    )

    cmd = [
        cartridge_cmd,
        'repair',
        'remove-instance',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        instance_uuid,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    # check logs
    logs = get_logs(output)
    assert logs[0] == "Remove instance with UUID %s" % config.instance_uuid

    instances_logs = logs[-len(instances):]
    assert_ok_for_all_instances(instances_logs, instances)

    # check config changes
    new_conf = get_conf_with_removed_instance(old_conf, config.instance_uuid)
    assert_conf_changed(conf_paths, other_app_conf_paths, old_conf, new_conf)
def test_remove_dry_run(cartridge_cmd, conf_type, tmpdir,
                        clusterwide_conf_simple, clusterwide_conf_srv_disabled,
                        clusterwide_conf_srv_expelled,
                        clusterwide_conf_srv_not_in_leaders,
                        clusterwide_conf_non_existent_rpl,
                        clusterwide_conf_srv_last_in_rpl):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    configs = {
        'simple': clusterwide_conf_simple,
        'disabled': clusterwide_conf_srv_disabled,
        'expelled': clusterwide_conf_srv_expelled,
        'not-in-leaders': clusterwide_conf_srv_not_in_leaders,
        'non-existent-rpl': clusterwide_conf_non_existent_rpl,
        'srv-last-in-rpl': clusterwide_conf_srv_last_in_rpl,
    }

    config = configs[conf_type]
    old_conf = copy.deepcopy(config.conf)
    instance_uuid = config.instance_uuid

    instance_conf = old_conf['servers'][instance_uuid]

    instances = ['instance-1', 'instance-2']
    conf_paths = write_instances_topology_conf(data_dir, APPNAME, old_conf,
                                               instances)

    cmd = [
        cartridge_cmd,
        'repair',
        'remove-instance',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        '--dry-run',
        instance_uuid,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    # check logs
    assert "Remove instance with UUID %s" % instance_uuid in output

    if conf_type == 'expelled':
        exp_srv_diff = '-  %s: expelled' % instance_uuid
    else:
        exp_srv_diff = '\n'.join([
            '-  %s:' % instance_uuid,
            '-    disabled: %s' %
            ('true' if instance_conf['disabled'] else 'false'),
            '-    replicaset_uuid: %s' % instance_conf['replicaset_uuid'],
            '-    uri: %s' % instance_conf['uri'],
        ])
    assert exp_srv_diff in output

    if conf_type == 'simple':
        replicaset_conf = old_conf['replicasets'][config.replicaset_uuid]
        exp_rpl_diff = '\n'.join([
            '   %s:' % config.replicaset_uuid,
            '     alias: %s' % replicaset_conf['alias'],
            '     master:',
            '     - srv-1',
            '     - srv-2',
            '-    - %s' % instance_uuid,
        ])
        assert exp_rpl_diff in output

    if conf_type == 'srv-last-in-rpl':
        replicaset_conf = old_conf['replicasets'][config.replicaset_uuid]
        exp_rpl_diff = '\n'.join([
            '-  %s:' % config.replicaset_uuid,
            '-    alias: %s' % replicaset_conf['alias'],
            '-    master:',
            '-    - %s' % instance_uuid,
        ])
        assert exp_rpl_diff in output

    # check config wasn't changed
    assert_conf_not_changed(conf_paths, old_conf)
def test_set_leader(cartridge_cmd, conf_type, tmpdir,
                    clusterwide_conf_simple,
                    clusterwide_conf_srv_not_in_leaders,
                    clusterwide_conf_other_leader_is_string,
                    clusterwide_conf_one_file):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    configs = {
        'simple': clusterwide_conf_simple,
        'not-in-leaders': clusterwide_conf_srv_not_in_leaders,
        'leader-is-string': clusterwide_conf_other_leader_is_string,
        'one-file-config': clusterwide_conf_one_file,
    }

    config = configs[conf_type]
    old_conf = copy.deepcopy(config.conf)

    # create app configs
    instances = ['instance-1', 'instance-2']
    conf_paths = write_instances_topology_conf(data_dir, APPNAME, old_conf, instances, config.one_file)

    # create other app configs
    other_instances = ['other-instance-1', 'other-instance-2']
    other_app_conf_paths = write_instances_topology_conf(
        data_dir, OTHER_APP_NAME, old_conf, other_instances, config.one_file,
    )

    cmd = [
        cartridge_cmd, 'repair', 'set-leader',
        '--name', APPNAME,
        '--data-dir', data_dir,
        config.replicaset_uuid, config.instance_uuid,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    # check logs
    logs = get_logs(output)
    assert logs[0] == "Set %s leader to %s" % (config.replicaset_uuid, config.instance_uuid)

    instances_logs = logs[-len(instances):]
    assert_ok_for_all_instances(instances_logs, instances)

    # check app config changes
    new_conf = copy.deepcopy(old_conf)

    # apply expected changes to topology conf
    new_topology_conf = new_conf
    if config.one_file:
        new_topology_conf = new_conf['topology']

    new_leaders = new_topology_conf['replicasets'][config.replicaset_uuid]['master']
    if type(new_leaders) == list:
        if config.instance_uuid in new_leaders:
            new_leaders.remove(config.instance_uuid)

        new_leaders.insert(0, config.instance_uuid)
    else:
        new_topology_conf['replicasets'][config.replicaset_uuid]['master'] = config.instance_uuid

    assert_conf_changed(conf_paths, other_app_conf_paths, old_conf, new_conf)
def test_set_leader_dry_run(cartridge_cmd, conf_type, tmpdir,
                            clusterwide_conf_simple,
                            clusterwide_conf_srv_not_in_leaders,
                            clusterwide_conf_other_leader_is_string):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    configs = {
        'simple': clusterwide_conf_simple,
        'not-in-leaders': clusterwide_conf_srv_not_in_leaders,
        'leader-is-string': clusterwide_conf_other_leader_is_string,
    }

    config = configs[conf_type]
    old_conf = copy.deepcopy(config.conf)

    exp_rpl_diffs = {
        'simple': '\n'.join([
            '   %s:' % config.replicaset_uuid,
            '     alias: unnamed',
            '     master:',
            '+    - %s' % config.instance_uuid,
            '     - srv-1',
            '     - srv-2',
            '-    - %s' % config.instance_uuid,
        ]),
        'not-in-leaders': '\n'.join([
            '   %s:' % config.replicaset_uuid,
            '     alias: unnamed',
            '     master:',
            '+    - %s' % config.instance_uuid,
            '     - srv-1',
            '     - srv-2',
        ]),
        'leader-is-string': '\n'.join([
            '   %s:' % config.replicaset_uuid,
            '     alias: unnamed',
            '-    master: srv-1',
            '+    master: %s' % config.instance_uuid,
        ]),
    }

    # create app working directories
    instances = ['instance-1', 'instance-2']
    conf_paths = write_instances_topology_conf(data_dir, APPNAME, old_conf, instances)

    cmd = [
        cartridge_cmd, 'repair', 'set-leader',
        '--name', APPNAME,
        '--data-dir', data_dir,
        '--dry-run',
        config.replicaset_uuid, config.instance_uuid,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    # check logs
    assert "Set %s leader to %s" % (config.replicaset_uuid, config.instance_uuid) in output

    exp_rpl_diff = exp_rpl_diffs[conf_type]
    assert exp_rpl_diff in output

    # check config wasn't changed
    assert_conf_not_changed(conf_paths, old_conf)
def test_force_list_topology(cartridge_cmd, tmpdir, clusterwide_conf_simple_v1,
                             clusterwide_conf_simple_v2):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    config1 = clusterwide_conf_simple_v1
    config2 = clusterwide_conf_simple_v2

    # create app configs
    conf1_instances = ['instance-1', 'instance-2']
    conf1_paths = write_instances_topology_conf(data_dir, APPNAME,
                                                config1.conf, conf1_instances)

    conf2_instances = ['instance-3', 'instance-4']
    conf2_paths = write_instances_topology_conf(data_dir, APPNAME,
                                                config2.conf, conf2_instances)

    # instances = conf1_instances + conf2_instances

    cmd = [
        cartridge_cmd,
        'repair',
        'list-topology',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        '--force',
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    assert_conf_not_changed(conf1_paths, config1.conf)
    assert_conf_not_changed(conf2_paths, config2.conf)

    lines = output.split('\n')
    logs = get_logs('\n'.join(lines[:3]))

    assert logs[0] == "Get current topology"
    assert "Clusterwide config is diverged between instances" in logs[1]
    assert logs[2] == "Process application cluster-wide configurations..."

    assert "Write application cluster-wide configurations..." not in output

    exp_summary_conf1 = '''   • instance-1, instance-2... OK
Instances
  * srv-1
    URI: localhost:3301
    replicaset: rpl-1
  * srv-2
    URI: srv-2-uri
    replicaset: rpl-1
  * srv-3
    URI: srv-3-uri
    replicaset: rpl-2
Replicasets
  * rpl-1
    roles:
     * vshard-storage
    instances:
     * srv-1
     * srv-2
  * rpl-2
    roles:
     * vshard-storage
    instances:
     * srv-3
'''

    exp_summary_conf2 = '''
   • instance-3, instance-4... OK
Instances
  * srv-1
    URI: localhost:3301
    replicaset: rpl-1
  * srv-2
    URI: srv-2-uri
    replicaset: rpl-1
  * srv-3
    URI: srv-3-uri
    replicaset: rpl-2
  * srv-4
    URI: srv-4-uri
    replicaset: rpl-2
Replicasets
  * rpl-1
    roles:
     * vshard-storage
    instances:
     * srv-1
     * srv-2
  * rpl-2
    roles:
     * vshard-storage
    instances:
     * srv-3
     * srv-4'''

    assert exp_summary_conf1 in output
    assert exp_summary_conf2 in output
def test_force_patch(cartridge_cmd, repair_cmd, tmpdir,
                     clusterwide_conf_simple_v1, clusterwide_conf_simple_v2):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    config1 = clusterwide_conf_simple_v1
    config2 = clusterwide_conf_simple_v2

    # create app configs
    conf1_instances = ['instance-1', 'instance-2']
    conf1_paths = write_instances_topology_conf(data_dir, APPNAME,
                                                config1.conf, conf1_instances)

    conf2_instances = ['instance-3', 'instance-4']
    conf2_paths = write_instances_topology_conf(data_dir, APPNAME,
                                                config2.conf, conf2_instances)

    instances = conf1_instances + conf2_instances

    args = simple_args.get(repair_cmd, [])
    cmd = [
        cartridge_cmd,
        'repair',
        repair_cmd,
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
        '--force',
    ]
    cmd.extend(args)

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    if repair_cmd == 'set-advertise-uri':
        first_log_line = "Set %s advertise URI to %s" % (args[0], args[1])
    elif repair_cmd == 'remove-instance':
        first_log_line = "Remove instance with UUID %s" % args[0]
    elif repair_cmd == 'set-leader':
        first_log_line = "Set %s leader to %s" % (args[0], args[1])

    logs = get_logs(output)
    assert logs[0] == first_log_line
    assert "Clusterwide config is diverged between instances" in logs[1]
    assert logs[2] == "Process application cluster-wide configurations..."

    process_conf_logs = logs[3:5]
    assert_ok_for_instances_group(process_conf_logs, conf1_instances)
    assert_ok_for_instances_group(process_conf_logs, conf2_instances)

    assert logs[5] == "Write application cluster-wide configurations..."

    write_conf_logs = logs[6:]
    assert_ok_for_all_instances(write_conf_logs, instances)

    # check config changes independently
    if repair_cmd == 'set-advertise-uri':
        new_conf1 = get_conf_with_new_uri(config1.conf, config1.instance_uuid,
                                          args[1])
        new_conf2 = get_conf_with_new_uri(config2.conf, config2.instance_uuid,
                                          args[1])
    elif repair_cmd == 'remove-instance':
        new_conf1 = get_conf_with_removed_instance(config1.conf, args[0])
        new_conf2 = get_conf_with_removed_instance(config2.conf, args[0])
    elif repair_cmd == 'set-leader':
        new_conf1 = get_conf_with_new_leader(config1.conf, args[0], args[1])
        new_conf2 = get_conf_with_new_leader(config2.conf, args[0], args[1])

    assert_conf_changed(conf1_paths, None, config1.conf, new_conf1)
    assert_conf_changed(conf2_paths, None, config2.conf, new_conf2)
def test_list_topology(cartridge_cmd, tmpdir):
    data_dir = os.path.join(tmpdir, 'tmp', 'data')
    os.makedirs(data_dir)

    old_conf = copy.deepcopy(SIMPLE_CONF)

    # create app configs
    instances = ['instance-1', 'instance-2']
    conf_paths = write_instances_topology_conf(data_dir, APPNAME, old_conf,
                                               instances)

    # create other app configs
    other_instances = ['other-instance-1', 'other-instance-2']
    other_app_conf_paths = write_instances_topology_conf(
        data_dir, OTHER_APP_NAME, old_conf, other_instances)

    cmd = [
        cartridge_cmd,
        'repair',
        'list-topology',
        '--name',
        APPNAME,
        '--data-dir',
        data_dir,
    ]

    rc, output = run_command_and_get_output(cmd, cwd=tmpdir)
    assert rc == 0

    assert_conf_not_changed(conf_paths, old_conf)
    assert_conf_not_changed(other_app_conf_paths, old_conf)

    lines = output.split('\n')
    logs = get_logs('\n'.join(lines[:3]))

    assert logs[0] == "Get current topology"
    assert logs[1] == "Process application cluster-wide configurations..."
    assert_ok_for_instances_group(logs, instances)

    summary = '\n'.join(lines[3:])

    exp_summary = '''Instances
  * srv-1-uuid
    URI: localhost:3301
    replicaset: rpl-1-uuid
  * srv-2-uuid
    URI: localhost:3302
    replicaset: rpl-1-uuid
  * srv-3-uuid
    URI: localhost:3303
    replicaset: rpl-1-uuid
  * srv-4-uuid
    URI: localhost:3304
    replicaset: rpl-2-uuid
  * srv-5-uuid
    URI: localhost:3305
    replicaset: rpl-1-uuid
  * srv-6-uuid disabled
    URI: localhost:3306
    replicaset: rpl-2-uuid
  * srv-expelled expelled
Replicasets
  * rpl-1-uuid
    roles:
     * vshard-storage
    instances:
     * srv-1-uuid
     * srv-2-uuid
     * srv-3-uuid
     * srv-5-uuid
  * rpl-2-uuid
    roles:
     * vshard-storage
    instances:
     * srv-4-uuid
     * srv-6-uuid

'''

    assert summary == exp_summary