Skip to content

Commit 9cb4ef6

Browse files
committed
Task to remove orphan symlinks
1 parent 1af4441 commit 9cb4ef6

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

readthedocs/projects/tasks.py

+19
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,25 @@ def symlink_domain(project_pk, domain_pk, delete=False):
778778
sym.symlink_cnames(domain)
779779

780780

781+
@app.task(queue='web')
782+
def remove_orphan_symlinks():
783+
"""
784+
Remove orphan symlinks.
785+
786+
List CNAME_ROOT for Public and Private symlinks, check that all the listed
787+
cname exist in the database and if doesn't exist, they are un-linked.
788+
"""
789+
for symlink in [PublicSymlink, PrivateSymlink]:
790+
for domain_path in [symlink.PROJECT_CNAME_ROOT, symlink.CNAME_ROOT]:
791+
for domain in os.listdir(domain_path):
792+
try:
793+
Domain.objects.get(domain=domain)
794+
except Domain.DoesNotExist:
795+
orphan_domain_path = os.path.join(domain_path, domain)
796+
log.info('Unlinking orphan CNAME: %s', orphan_domain_path)
797+
os.unlink(orphan_domain_path)
798+
799+
781800
@app.task(queue='web')
782801
def symlink_subproject(project_pk):
783802
project = Project.objects.get(pk=project_pk)

readthedocs/rtd_tests/tests/test_project_symlinks.py

+74
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from readthedocs.builds.models import Version
1717
from readthedocs.projects.models import Project, Domain
18+
from readthedocs.projects.tasks import remove_orphan_symlinks
1819
from readthedocs.core.symlink import PublicSymlink, PrivateSymlink
1920

2021

@@ -166,6 +167,79 @@ def test_symlink_cname(self):
166167
filesystem['private_web_root'] = public_root
167168
self.assertFilesystem(filesystem)
168169

170+
def test_symlink_remove_orphan_symlinks(self):
171+
self.domain = get(Domain, project=self.project, domain='woot.com',
172+
url='http://woot.com', cname=True)
173+
self.symlink.symlink_cnames()
174+
175+
# Editing the Domain and calling save will symlink the new domain and
176+
# leave the old one as orphan.
177+
self.domain.domain = 'foobar.com'
178+
self.domain.save()
179+
180+
filesystem = {
181+
'private_cname_project': {
182+
'foobar.com': {'type': 'link', 'target': 'user_builds/kong'},
183+
'woot.com': {'type': 'link', 'target': 'user_builds/kong'},
184+
},
185+
'private_cname_root': {
186+
'foobar.com': {'type': 'link', 'target': 'private_web_root/kong'},
187+
'woot.com': {'type': 'link', 'target': 'private_web_root/kong'},
188+
},
189+
'private_web_root': {'kong': {'en': {}}},
190+
'public_cname_project': {
191+
'foobar.com': {'type': 'link', 'target': 'user_builds/kong'},
192+
'woot.com': {'type': 'link', 'target': 'user_builds/kong'},
193+
},
194+
'public_cname_root': {
195+
'foobar.com': {'type': 'link', 'target': 'public_web_root/kong'},
196+
'woot.com': {'type': 'link', 'target': 'public_web_root/kong'},
197+
},
198+
'public_web_root': {
199+
'kong': {'en': {'latest': {
200+
'type': 'link',
201+
'target': 'user_builds/kong/rtd-builds/latest',
202+
}}}
203+
}
204+
}
205+
if self.privacy == 'private':
206+
public_root = filesystem['public_web_root'].copy()
207+
private_root = filesystem['private_web_root'].copy()
208+
filesystem['public_web_root'] = private_root
209+
filesystem['private_web_root'] = public_root
210+
self.assertFilesystem(filesystem)
211+
212+
remove_orphan_symlinks()
213+
filesystem = {
214+
'private_cname_project': {
215+
'foobar.com': {'type': 'link', 'target': 'user_builds/kong'},
216+
},
217+
'private_cname_root': {
218+
'foobar.com': {'type': 'link', 'target': 'private_web_root/kong'},
219+
},
220+
'private_web_root': {'kong': {'en': {}}},
221+
'public_cname_project': {
222+
'foobar.com': {'type': 'link', 'target': 'user_builds/kong'},
223+
},
224+
'public_cname_root': {
225+
'foobar.com': {'type': 'link', 'target': 'public_web_root/kong'},
226+
},
227+
'public_web_root': {
228+
'kong': {'en': {'latest': {
229+
'type': 'link',
230+
'target': 'user_builds/kong/rtd-builds/latest',
231+
}}},
232+
},
233+
}
234+
if self.privacy == 'private':
235+
public_root = filesystem['public_web_root'].copy()
236+
private_root = filesystem['private_web_root'].copy()
237+
filesystem['public_web_root'] = private_root
238+
filesystem['private_web_root'] = public_root
239+
240+
self.assertFilesystem(filesystem)
241+
242+
169243
def test_symlink_cname_dont_link_missing_domains(self):
170244
"""Domains should be relinked after deletion"""
171245
self.domain = get(Domain, project=self.project, domain='woot.com',

0 commit comments

Comments
 (0)