Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy dir if symlink fails #7447

Merged
merged 6 commits into from
Aug 9, 2023
Merged

Conversation

anjutiwari
Copy link
Contributor

@anjutiwari anjutiwari commented Apr 24, 2023

resolves #7428
resolves #8223

Description

dbt deps command fails to run in databricks DBFS. Copy dir in case if any symlink fails with expection

Checklist

@anjutiwari anjutiwari requested review from a team as code owners April 24, 2023 15:47
@cla-bot cla-bot bot added the cla:yes label Apr 24, 2023
if system.path_exists(dest_path):
if not system.path_is_symlink(dest_path):
system.rmdir(dest_path)
else:
system.remove_file(dest_path)

if can_create_symlink:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if can_create_symlink check shouldn't be removed. It helps for the cases where symlink function doesn't exist on os, in which case AttributeError would be thrown.

except OSError should be added as an edge case like ours, where os.symlink function exists but it still fails.

Something like:

symlink_supported = False

if can_create_symlink:
    try:
        fire_event(DepsCreatingLocalSymlink())
        system.make_symlink(src_path, dest_path)
    except OSError:
        pass
    else:
        symlink_supported = True
if not symlink_supported:
    fire_event(DepsSymlinkNotAvailable())
    shutil.copytree(src_path, dest_path)

Copy link
Contributor Author

@anjutiwari anjutiwari Apr 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think we need it, make_symlink calling it. The functionality remains the same. Check make_symlink method.
https://github.com/anjutiwari/dbt-core/blob/main/core/dbt/clients/system.py#L156
https://docs.getdbt.com/faqs/core/install-pip-os-prereqs.md

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make_symlink method will throw dbt.exceptions.SymbolicLinkError, in which case except OSError block here won't handle it.
The behaviour is changed for the case where symlink function attribute isn't present on os

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think we should use dbt.exceptions.SymbolicLinkError, and we should also catch the SymbolicLinkError.

Also, I am curious about which OS does not have symlinks function in python lib(os) package, as mentioned in my Issue description.
As per the dbt, we have a list of supported operating systems and condition on python3.7+. https://docs.getdbt.com/faqs/core/install-pip-os-prereqs.md

If my understanding is true, we may not have any scenarios where lib(os) package will not have a symlink function and we may not need to handle the SymbolicLinkError exception.

Waiting for the core reviewers to help us here.

LocalPinnedPackage("local").install("dummy", "dummy")
self.assertEqual(mock_shutil.call_count, 1)
mock_shutil.assert_called_once_with("/tmp/source", "/tmp/dest")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add test where system.supports_symlinks() returns False

Copy link
Contributor Author

@anjutiwari anjutiwari Apr 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was to handle the tests for only the newly added code.

Copy link

@nitinbhojwani nitinbhojwani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

system.supports_symlinks() check should continue to exist before trying to invoke symlink on os

Along with that, the edge case handling of OSError exception on system.make_symlink should be done.

fire_event(DepsCreatingLocalSymlink())
system.make_symlink(src_path, dest_path)

else:
except OSError:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jtcohen6 jtcohen6 added Team:Language ready_for_review Externally contributed PR has functional approval, ready for code review from Core engineering labels Apr 25, 2023
@chronitis
Copy link

Just a note that I think this PR fixes wider problems than just those related to databricks DBFS.

When using a local: PATH package on Windows, DBT will attempt to create a symlink (since supports_symlink() is true), but unless the user has administrator permissions or specific group policy, creating the symlink fails. If I read this PR right, it would also fix this issue.

@anjutiwari
Copy link
Contributor Author

Thanks @chronitis for pointing out another edge case. Let me try to reproduce this scenario and verify if this solution is already fixing the problem.

@anjutiwari
Copy link
Contributor Author

Hey @jtcohen6,
Just wanted to check for any update on this. Please let me know if I could make this PR more smooth to get it prioritized for the review.

Thank you

@gshank
Copy link
Contributor

gshank commented Jun 28, 2023

Sorry for the delay in processing this. We are getting close to a release and it would be nice to get this in. Could you fix the merge conflict in test_deps.py?

@anjutiwari
Copy link
Contributor Author

Thanks @gshank. Fixing it.

@gshank gshank closed this Jul 20, 2023
@gshank gshank reopened this Jul 20, 2023
@codecov
Copy link

codecov bot commented Jul 20, 2023

Codecov Report

Merging #7447 (abb6c24) into main (44d1e73) will decrease coverage by 0.02%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #7447      +/-   ##
==========================================
- Coverage   86.28%   86.26%   -0.02%     
==========================================
  Files         174      174              
  Lines       25518    25518              
==========================================
- Hits        22019    22014       -5     
- Misses       3499     3504       +5     
Files Changed Coverage Δ
core/dbt/deps/local.py 96.00% <100.00%> (+4.00%) ⬆️

... and 1 file with indirect coverage changes

@VersusFacit VersusFacit added the test postgres Run integration tests for the Postgres adapter in CI. label Aug 8, 2023
@dbeatty10
Copy link
Contributor

Just a note that I think this PR fixes wider problems than just those related to databricks DBFS.

When using a local: PATH package on Windows, DBT will attempt to create a symlink (since supports_symlink() is true), but unless the user has administrator permissions or specific group policy, creating the symlink fails. If I read this PR right, it would also fix this issue.

Very good point @chronitis ! This PR does look like it addresses use cases beyond Databricks DBFS, namely any time a symlink doesn't work. For example, it would also resolve #8223.

@gshank gshank closed this Aug 8, 2023
@gshank gshank reopened this Aug 8, 2023
@gshank gshank merged commit 8c98ef3 into dbt-labs:main Aug 9, 2023
47 of 48 checks passed
aranke pushed a commit that referenced this pull request Sep 5, 2023
aranke added a commit that referenced this pull request Sep 5, 2023
@aranke aranke mentioned this pull request Jul 12, 2024
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport 1.6.latest cla:yes ready_for_review Externally contributed PR has functional approval, ready for code review from Core engineering test postgres Run integration tests for the Postgres adapter in CI.
Projects
None yet
8 participants