Skip to content

Commit 7d464fc

Browse files
authored
fix: keep the ftp dir in sync when the datatracker creates artifacts (ietf-tools#8401)
* chore: fix typo in log message * fix: write new conflict reviews to the ftp directory * fix: log exception description * chore: avoid reusing a name for mypy * fix: write non-meeting-related slides to ftp/slides * fix: write status changes to ftp dir * fix: copy draft yang modules to the ftp dir the last commit above (see ietf-tools#8401) has no tests :(. There aren't tests of this yang scaffolding to add to. Adding a set of tests should be an independent larger effort.
1 parent 8b7fa11 commit 7d464fc

9 files changed

Lines changed: 95 additions & 22 deletions

ietf/doc/tests_conflict_review.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import io
66
import os
7+
from pathlib import Path
78

89
from pyquery import PyQuery
910
from textwrap import wrap
@@ -387,7 +388,7 @@ def setUp(self):
387388

388389

389390
class ConflictReviewSubmitTests(TestCase):
390-
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['CONFLICT_REVIEW_PATH']
391+
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['CONFLICT_REVIEW_PATH','FTP_PATH']
391392
def test_initial_submission(self):
392393
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
393394
url = urlreverse('ietf.doc.views_conflict_review.submit',kwargs=dict(name=doc.name))
@@ -403,16 +404,23 @@ def test_initial_submission(self):
403404
# Right now, nothing to test - we let people put whatever the web browser will let them put into that textbox
404405

405406
# sane post using textbox
406-
path = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (doc.name, doc.rev))
407+
basename = f"{doc.name}-{doc.rev}.txt"
408+
path = Path(settings.CONFLICT_REVIEW_PATH) / basename
409+
ftp_dir = Path(settings.FTP_DIR) / "conflict-reviews"
410+
if not ftp_dir.exists():
411+
ftp_dir.mkdir()
412+
ftp_path = ftp_dir / basename
407413
self.assertEqual(doc.rev,'00')
408-
self.assertFalse(os.path.exists(path))
414+
self.assertFalse(path.exists())
415+
self.assertFalse(ftp_path.exists())
409416
r = self.client.post(url,dict(content="Some initial review text\n",submit_response="1"))
410417
self.assertEqual(r.status_code,302)
411418
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
412419
self.assertEqual(doc.rev,'00')
413420
with io.open(path) as f:
414421
self.assertEqual(f.read(),"Some initial review text\n")
415422
f.close()
423+
self.assertTrue(ftp_path.exists())
416424
self.assertTrue( "submission-00" in doc.latest_event(NewRevisionDocEvent).desc)
417425

418426
def test_subsequent_submission(self):

ietf/doc/tests_material.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929

3030
class GroupMaterialTests(TestCase):
31-
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['AGENDA_PATH']
31+
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['AGENDA_PATH', 'FTP_DIR']
3232
def setUp(self):
3333
super().setUp()
3434
self.materials_dir = self.tempdir("materials")
@@ -37,6 +37,10 @@ def setUp(self):
3737
self.slides_dir.mkdir()
3838
self.saved_document_path_pattern = settings.DOCUMENT_PATH_PATTERN
3939
settings.DOCUMENT_PATH_PATTERN = self.materials_dir + "/{doc.type_id}/"
40+
self.assertTrue(Path(settings.FTP_DIR).exists())
41+
ftp_slides_dir = Path(settings.FTP_DIR) / "slides"
42+
if not ftp_slides_dir.exists():
43+
ftp_slides_dir.mkdir()
4044

4145
self.meeting_slides_dir = Path(settings.AGENDA_PATH) / "42" / "slides"
4246
if not self.meeting_slides_dir.exists():
@@ -112,7 +116,12 @@ def test_upload_slides(self):
112116
self.assertEqual(doc.title, "Test File - with fancy title")
113117
self.assertEqual(doc.get_state_slug(), "active")
114118

115-
with io.open(os.path.join(self.materials_dir, "slides", doc.name + "-" + doc.rev + ".pdf")) as f:
119+
basename=f"{doc.name}-{doc.rev}.pdf"
120+
filepath=Path(self.materials_dir) / "slides" / basename
121+
with filepath.open() as f:
122+
self.assertEqual(f.read(), content)
123+
ftp_filepath=Path(settings.FTP_DIR) / "slides" / basename
124+
with ftp_filepath.open() as f:
116125
self.assertEqual(f.read(), content)
117126

118127
# check that posting same name is prevented

ietf/doc/tests_status_change.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import io
66
import os
7+
from pathlib import Path
78

89
import debug # pyflakes:ignore
910

@@ -540,7 +541,7 @@ def setUp(self):
540541
DocumentFactory(type_id='statchg',name='status-change-imaginary-mid-review',notify='notify@example.org')
541542

542543
class StatusChangeSubmitTests(TestCase):
543-
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['STATUS_CHANGE_PATH']
544+
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['STATUS_CHANGE_PATH', 'FTP_PATH']
544545
def test_initial_submission(self):
545546
doc = Document.objects.get(name='status-change-imaginary-mid-review')
546547
url = urlreverse('ietf.doc.views_status_change.submit',kwargs=dict(name=doc.name))
@@ -556,14 +557,19 @@ def test_initial_submission(self):
556557
# Right now, nothing to test - we let people put whatever the web browser will let them put into that textbox
557558

558559
# sane post using textbox
559-
path = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.name, doc.rev))
560560
self.assertEqual(doc.rev,'00')
561-
self.assertFalse(os.path.exists(path))
561+
basename = f"{doc.name}-{doc.rev}.txt"
562+
filepath = Path(settings.STATUS_CHANGE_PATH) / basename
563+
ftp_filepath = Path(settings.FTP_DIR) / "status-changes" / basename
564+
self.assertFalse(filepath.exists())
565+
self.assertFalse(ftp_filepath.exists())
562566
r = self.client.post(url,dict(content="Some initial review text\n",submit_response="1"))
563567
self.assertEqual(r.status_code,302)
564568
doc = Document.objects.get(name='status-change-imaginary-mid-review')
565569
self.assertEqual(doc.rev,'00')
566-
with io.open(path) as f:
570+
with filepath.open() as f:
571+
self.assertEqual(f.read(),"Some initial review text\n")
572+
with ftp_filepath.open() as f:
567573
self.assertEqual(f.read(),"Some initial review text\n")
568574
self.assertTrue( "mid-review-00" in doc.latest_event(NewRevisionDocEvent).desc)
569575

@@ -628,3 +634,6 @@ def test_subsequent_submission(self):
628634
def setUp(self):
629635
super().setUp()
630636
DocumentFactory(type_id='statchg',name='status-change-imaginary-mid-review',notify='notify@example.org')
637+
ftp_subdir=Path(settings.FTP_DIR)/"status-changes"
638+
if not ftp_subdir.exists():
639+
ftp_subdir.mkdir()

ietf/doc/utils_charter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ def fix_charter_revision_after_approval(charter, by):
112112
)
113113
try:
114114
os.link(new, ftp_filepath)
115-
except IOError:
115+
except IOError as ex:
116116
log(
117-
"There was an error creating a harlink at %s pointing to %s"
118-
% (ftp_filepath, new)
117+
"There was an error creating a hardlink at %s pointing to %s: %s"
118+
% (ftp_filepath, new, ex)
119119
)
120120

121121
events = []

ietf/doc/views_conflict_review.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import datetime
66
import io
77
import os
8+
from pathlib import Path
89

910
from django import forms
1011
from django.shortcuts import render, get_object_or_404, redirect
@@ -181,12 +182,21 @@ def clean_txt(self):
181182
return get_cleaned_text_file_content(self.cleaned_data["txt"])
182183

183184
def save(self, review):
184-
filename = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (review.name, review.rev))
185-
with io.open(filename, 'w', encoding='utf-8') as destination:
185+
basename = f"{review.name}-{review.rev}.txt"
186+
filepath = Path(settings.CONFLICT_REVIEW_PATH) / basename
187+
with filepath.open('w', encoding='utf-8') as destination:
186188
if self.cleaned_data['txt']:
187189
destination.write(self.cleaned_data['txt'])
188190
else:
189191
destination.write(self.cleaned_data['content'])
192+
ftp_filepath = Path(settings.FTP_DIR) / "conflict-reviews" / basename
193+
try:
194+
os.link(filepath, ftp_filepath) # Path.hardlink_to is not available until 3.10
195+
except IOError as e:
196+
log.log(
197+
"There was an error creating a hardlink at %s pointing to %s: %s"
198+
% (ftp_filepath, filepath, e)
199+
)
190200

191201
#This is very close to submit on charter - can we get better reuse?
192202
@role_required('Area Director','Secretariat')

ietf/doc/views_material.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44

55
# views for managing group materials (slides, ...)
6-
import io
76
import os
7+
from pathlib import Path
88
import re
99

1010
from django import forms
@@ -162,9 +162,21 @@ def edit_material(request, name=None, acronym=None, action=None, doc_type=None):
162162
f = form.cleaned_data["material"]
163163
file_ext = os.path.splitext(f.name)[1]
164164

165-
with io.open(os.path.join(doc.get_file_path(), doc.name + "-" + doc.rev + file_ext), 'wb+') as dest:
165+
basename = f"{doc.name}-{doc.rev}{file_ext}" # Note the lack of a . before file_ext - see os.path.splitext
166+
filepath = Path(doc.get_file_path()) / basename
167+
with filepath.open('wb+') as dest:
166168
for chunk in f.chunks():
167169
dest.write(chunk)
170+
if not doc.meeting_related():
171+
log.assertion('doc.type_id == "slides"')
172+
ftp_filepath = Path(settings.FTP_DIR) / doc.type_id / basename
173+
try:
174+
os.link(filepath, ftp_filepath) # Path.hardlink is not available until 3.10
175+
except IOError as ex:
176+
log.log(
177+
"There was an error creating a hardlink at %s pointing to %s: %s"
178+
% (ftp_filepath, filepath, ex)
179+
)
168180

169181
if prev_rev != doc.rev:
170182
e = NewRevisionDocEvent(type="new_revision", doc=doc, rev=doc.rev)

ietf/doc/views_status_change.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import datetime
66
import io
77
import os
8+
from pathlib import Path
89
import re
910

1011
from typing import Dict # pyflakes:ignore
@@ -33,6 +34,7 @@
3334
from ietf.mailtrigger.utils import gather_address_lists
3435
from ietf.name.models import DocRelationshipName, StdLevelName
3536
from ietf.person.models import Person
37+
from ietf.utils.log import log
3638
from ietf.utils.mail import send_mail_preformatted
3739
from ietf.utils.textupload import get_cleaned_text_file_content
3840
from ietf.utils.timezone import date_today, DEADLINE_TZINFO
@@ -154,12 +156,21 @@ def clean_txt(self):
154156
return get_cleaned_text_file_content(self.cleaned_data["txt"])
155157

156158
def save(self, doc):
157-
filename = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.name, doc.rev))
158-
with io.open(filename, 'w', encoding='utf-8') as destination:
159-
if self.cleaned_data['txt']:
160-
destination.write(self.cleaned_data['txt'])
161-
else:
162-
destination.write(self.cleaned_data['content'])
159+
basename = f"{doc.name}-{doc.rev}.txt"
160+
filename = Path(settings.STATUS_CHANGE_PATH) / basename
161+
with io.open(filename, 'w', encoding='utf-8') as destination:
162+
if self.cleaned_data['txt']:
163+
destination.write(self.cleaned_data['txt'])
164+
else:
165+
destination.write(self.cleaned_data['content'])
166+
try:
167+
ftp_filename = Path(settings.FTP_DIR) / "status-changes" / basename
168+
os.link(filename, ftp_filename) # Path.hardlink is not available until 3.10
169+
except IOError as ex:
170+
log(
171+
"There was an error creating a hardlink at %s pointing to %s: %s"
172+
% (ftp_filename, filename, ex)
173+
)
163174

164175
#This is very close to submit on charter - can we get better reuse?
165176
@role_required('Area Director','Secretariat')

ietf/submit/checkers.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import io
66
import os
7+
from pathlib import Path
78
import re
89
import shutil
910
import sys
@@ -280,6 +281,15 @@ def check_file_txt(self, path):
280281

281282
dest = os.path.join(settings.SUBMIT_YANG_DRAFT_MODEL_DIR, model)
282283
shutil.move(path, dest)
284+
ftp_dest = Path(settings.FTP_DIR) / "yang" / "draftmod" / model
285+
try:
286+
os.link(dest, ftp_dest)
287+
except IOError as ex:
288+
log(
289+
"There was an error creating a hardlink at %s pointing to %s: %s"
290+
% (ftp_dest, dest, ex)
291+
)
292+
283293

284294
# summary result
285295
results.append({

ietf/submit/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import os
99
import pathlib
1010
import re
11+
import subprocess
1112
import sys
1213
import time
1314
import traceback
@@ -1596,3 +1597,6 @@ def active(dirent):
15961597
modfile.unlink()
15971598
except UnicodeDecodeError as e:
15981599
log.log(f"Error processing {item.name}: {e}")
1600+
1601+
ftp_moddir = Path(settings.FTP_DIR) / "yang" / "draftmod"
1602+
subprocess.call(("/usr/bin/rsync", "-aq", "--delete", moddir, ftp_moddir))

0 commit comments

Comments
 (0)