def test_get_all_nonschema_objects_and_owners(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) expected = { SCHEMAS[0]: [ context.ObjectInfo('tables', quoted_object(SCHEMAS[0], TABLES[0]), ROLES[0], False), context.ObjectInfo('sequences', quoted_object(SCHEMAS[0], SEQUENCES[1]), ROLES[0], False), ], SCHEMAS[1]: [ context.ObjectInfo('tables', quoted_object(SCHEMAS[1], TABLES[0]), ROLES[1], False), context.ObjectInfo('sequences', quoted_object(SCHEMAS[1], SEQUENCES[2]), ROLES[1], False), ], } actual = dbcontext.get_all_nonschema_objects_and_owners() # We are deliberately not checking pg_catalog or information_schema here since that's a # lot of work and those should not be touched for k, v in expected.items(): assert set(v) == set(actual[k]) # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_nonschema_objects_and_owners() assert actual_again == actual
def verify_spec(rendered_template, spec, cursor, verbose, attributes, memberships, ownerships, privileges): assert isinstance(spec, dict) dbcontext = context.DatabaseContext(cursor, verbose) error_messages = [] # Having all roles represented exactly once is critical for all submodules # so we check this regardless of which submodules are being used error_messages += ensure_no_duplicate_roles(rendered_template) error_messages += ensure_no_undocumented_roles(spec, dbcontext) error_messages += ensure_no_except_on_schema(spec) if ownerships: for objkind in context.PRIVILEGE_MAP.keys(): if objkind == 'schemas': error_messages += ensure_no_unowned_schemas(spec, dbcontext) error_messages += ensure_no_schema_owned_twice(spec) else: # We run each of these functions once per object kind as it is possible that # two objects of different kinds could have the same name in the same schema error_messages += ensure_no_missing_objects( spec, dbcontext, objkind) error_messages += ensure_no_object_owned_twice( spec, dbcontext, objkind) error_messages += ensure_no_dependent_object_is_owned( spec, dbcontext, objkind) if privileges: error_messages += ensure_no_redundant_privileges(spec) if error_messages: common.fail('\n'.join(error_messages))
def test_get_schema_objects_no_entry(): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False) dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: { common.ObjectName('foo'): 'bar', } actual = dbcontext.get_schema_objects(common.ObjectName('key_not_in_response')) assert actual == []
def test_get_schema_owner(): schema = common.ObjectName('foo') expected_owner = 'bar' dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_schemas_and_owners'] = lambda: {schema: expected_owner} actual = dbcontext.get_schema_owner(schema) assert actual == expected_owner
def test_get_schema_objects(): schema = common.ObjectName('foo') expected = 'bar' dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False) dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: { common.ObjectName('foo'): expected } actual = dbcontext.get_schema_objects(schema) assert actual == expected
def test_get_role_current_defaults(rolename, object_kind, access, expected): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_current_defaults'] = lambda: { 'role1': { 'object_kind1': { 'access1': set([1, 2, 3]) } } } assert dbcontext.get_role_current_defaults(rolename, object_kind, access) == expected
def test_get_schema_objects_no_entry(): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False) dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: { 'foo': [ context.ObjectInfo('tables', quoted_object(SCHEMAS[0], TABLES[0]), ROLES[0], False), context.ObjectInfo('sequences', quoted_object(SCHEMAS[0], SEQUENCES[1]), ROLES[0], False), ], } actual = dbcontext.get_schema_objects('key_not_in_response') assert actual == []
def test_get_schema_objects(): schema = 'foo' expected = [ context.ObjectInfo('tables', quoted_object(SCHEMAS[0], TABLES[0]), ROLES[0], False), context.ObjectInfo('sequences', quoted_object(SCHEMAS[0], SEQUENCES[1]), ROLES[0], False), ] dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False) dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: {schema: expected} actual = dbcontext.get_schema_objects(schema) assert actual == expected
def test_get_all_role_attributes(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) actual = dbcontext.get_all_role_attributes() expected = set(['test_user', 'postgres', ROLES[0], ROLES[1]]) assert set(actual.keys()) == expected # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_role_attributes() assert actual_again == actual
def test_get_all_personal_schemas(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) actual = dbcontext.get_all_personal_schemas() expected = set(ROLES[1:3]) assert actual == expected # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_personal_schemas() assert actual_again == actual
def test_get_all_raw_object_attributes(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) raw_results = dbcontext.get_all_raw_object_attributes() assert isinstance(raw_results, list) assert len(raw_results) > 0 assert isinstance(raw_results[0], tuple) # Make sure that this data is cached for future use cursor.close() raw_results_again = dbcontext.get_all_raw_object_attributes() assert raw_results_again == raw_results
def test_get_version_info(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) actual = dbcontext.get_version_info() assert isinstance(actual, context.VersionInfo) assert not actual.is_redshift assert not actual.redshift_version # We do not check the Postgres version since we test against multiple Postgres versions # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_version_info() assert actual_again == actual
def test_get_role_objects_with_access(access, expected): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_current_nondefaults'] = lambda: { ROLES[0]: { 'tables': { 'read': set([ (quoted_object(SCHEMAS[0], TABLES[0]), 'SELECT'), (quoted_object(SCHEMAS[0], TABLES[1]), 'SELECT'), ]) } } } actual = dbcontext.get_role_objects_with_access(ROLES[0], SCHEMAS[0], 'tables', access) assert actual == expected
def test_get_role_current_nondefaults(rolename, object_kind, access, expected): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_current_nondefaults'] = lambda: { 'role1': { 'object_kind1': { 'access1': set([ (common.ObjectName('foo', 'bar'), 'SELECT'), (common.ObjectName('foo', 'baz'), 'SELECT'), (common.ObjectName('foo', 'qux'), 'INSERT'), ]) } } } actual = dbcontext.get_role_current_nondefaults(rolename, object_kind, access) assert actual == expected
def test_has_default_privilege(rolename, schema, object_kind, access, expected): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_current_defaults'] = lambda: { 'role1': { 'tables': { 'read': set([ ('role1', common.ObjectName('schema2'), 'SELECT'), ]), 'write': set([ ('not_this_role', common.ObjectName('schema1'), 'UPDATE'), ]), } } } assert dbcontext.has_default_privilege(rolename, schema, object_kind, access) == expected
def test_get_all_role_attributes(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) expected = set(['test_user', 'postgres', ROLES[0], ROLES[1]]) pg_version = dbcontext.get_version_info().postgres_version # Postgres 10 introduces several new roles that we have to account for if pg_version.startswith('10.'): expected.update(set([ 'pg_read_all_settings', 'pg_stat_scan_tables', 'pg_read_all_stats', 'pg_monitor'] )) actual = dbcontext.get_all_role_attributes() assert set(actual.keys()) == expected # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_role_attributes() assert actual_again == actual
def test_get_all_current_defaults(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) expected = { ROLES[0]: { 'tables': { 'read': set([ (ROLES[3], SCHEMAS[0], 'SELECT'), ]), 'write': set(), } } } actual = dbcontext.get_all_current_defaults() assert actual == expected # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_current_defaults() assert actual_again == expected
def test_get_all_memberships(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) expected = set([('role1', 'role0'), ('role2', 'role1')]) pg_version = dbcontext.get_version_info().postgres_version # Postgres 10 introduces several new roles and memberships that we have to account for if pg_version >= 100000: expected.update(set([ ('pg_monitor', 'pg_stat_scan_tables'), ('pg_monitor', 'pg_read_all_stats'), ('pg_monitor', 'pg_read_all_settings'), ])) actual = dbcontext.get_all_memberships() assert isinstance(actual, list) assert len(actual) == len(expected) # Convert actual to a set of tuples so comparison is easier actual_converted = set([tuple(i) for i in actual]) assert actual_converted == expected
def test_get_all_schemas_and_owners(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) expected = { SCHEMAS[0]: ROLES[0], SCHEMAS[1]: ROLES[0], SCHEMAS[2]: ROLES[1], ROLES[1]: ROLES[1], # These already existed 'public': 'postgres', 'information_schema': 'postgres', 'pg_catalog': 'postgres', } actual = dbcontext.get_all_schemas_and_owners() assert actual == expected # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_schemas_and_owners() assert actual_again == actual
def test_get_all_object_attributes(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) expected = { 'tables': { SCHEMAS[0]: { common.ObjectName(SCHEMAS[0], TABLES[0]): {'owner': ROLES[1], 'is_dependent': False}, common.ObjectName(SCHEMAS[0], TABLES[1]): {'owner': ROLES[1], 'is_dependent': False}, common.ObjectName(SCHEMAS[0], TABLES[2]): {'owner': ROLES[3], 'is_dependent': False}, } }, 'sequences': { SCHEMAS[0]: { common.ObjectName(SCHEMAS[0], SEQUENCES[0]): {'owner': ROLES[1], 'is_dependent': False}, common.ObjectName(SCHEMAS[0], SEQUENCES[1]): {'owner': ROLES[2], 'is_dependent': False}, common.ObjectName(SCHEMAS[0], SEQUENCES[2]): {'owner': ROLES[2], 'is_dependent': False}, } }, 'schemas': { SCHEMAS[0]: { common.ObjectName(SCHEMAS[0]): {'owner': ROLES[0], 'is_dependent': False}, }, 'public': { 'public': {'owner': 'postgres', 'is_dependent': False}, } } } actual = dbcontext.get_all_object_attributes() # We do this to avoid having to look at / filter out entries from # information_schema or pg_catalog for key in expected.keys(): expected_entries = expected[key][SCHEMAS[0]] actual_entries = actual[key][SCHEMAS[0]] assert expected_entries == actual_entries # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_object_attributes() assert actual_again == actual
def test_get_all_current_nondefaults(cursor): dbcontext = context.DatabaseContext(cursor, verbose=True) expected = { ROLES[0]: { 'tables': { 'read': set([ (quoted_object(SCHEMAS[0], TABLES[1]), 'SELECT'), (quoted_object(SCHEMAS[1], TABLES[3]), 'SELECT'), ]), 'write': set(), } }, ROLES[2]: { 'schemas': { 'read': set(), 'write': set([ (SCHEMAS[0], 'CREATE'), (SCHEMAS[1], 'CREATE'), ]), } }, ROLES[3]: { 'schemas': { 'read': set(), 'write': set([ (SCHEMAS[0], 'CREATE'), (SCHEMAS[1], 'CREATE'), ]), } } } actual = dbcontext.get_all_current_nondefaults() assert actual == expected # Make sure that this data is cached for future use cursor.close() actual_again = dbcontext.get_all_current_nondefaults() assert actual_again == expected
def test_is_superuser(all_role_attributes, expected): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_role_attributes'] = lambda: all_role_attributes actual = dbcontext.is_superuser(ROLES[0]) assert actual == expected
def test_get_role_attributes_role_does_not_exist(): dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_role_attributes'] = lambda: {} actual = dbcontext.get_role_attributes(ROLES[0]) assert actual == dict()
def test_get_role_attributes(): expected = {'foo': 'bar'} dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True) dbcontext._cache['get_all_role_attributes'] = lambda: {ROLES[0]: expected} actual = dbcontext.get_role_attributes(ROLES[0]) assert actual == expected