8000 feat: write objects to blob storage by rjsparks · Pull Request #8557 · ietf-tools/datatracker · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: write objects to blob storage #8557

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

Merged
merged 111 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
328f3b5
feat: basic blobstore infrastructure for dev
rjsparks Nov 12, 2024
5d5aea1
refactor: (broken) attempt to put minio console behind nginx
rjsparks Nov 13, 2024
be13bd6
feat: initialize blobstore with boto3
rjsparks Nov 14, 2024
9999edc
fix: abandon attempt to proxy minio. Use docker compose instead.
rjsparks Nov 18, 2024
e4b3dcd
ci: Merge branch 'main' into feat/blob
rjsparks Nov 27, 2024
c1d5a29
Merge branch 'main' into feat/blob
rjsparks Jan 10, 2025
6fc2241
feat: beginning of blob writes
rjsparks Jan 15, 2025
658dd7c
feat: storage utilities
rjsparks Jan 15, 2025
c8bf16c
feat: test buckets
rjsparks Jan 16, 2025
6e877ce
chore: black
rjsparks Jan 16, 2025
cdc2918
chore: remove unused import
rjsparks Jan 16, 2025
6baf663
chore: avoid f string when not needed
rjsparks Jan 16, 2025
d79abbd
fix: inform all settings files about blobstores
rjsparks Jan 16, 2025
a46165b
fix: declare types for some settings
rjsparks Jan 16, 2025
2304db8
ci: point to new target base
rjsparks Jan 16, 2025
4a762ac
Merge remote-tracking branch 'ietf-tools/main' into feat/blobwrites
rjsparks Jan 16, 2025
13b828e
ci: adjust test workflow
rjsparks Jan 16, 2025
7223a9c
fix: give the tests debug environment a blobstore
rjsparks Jan 16, 2025
5ad71a5
fix: "better" name declarations
rjsparks Jan 16, 2025
07f63e7
Merge remote-tracking branch 'ietf-tools/main' into feat/blobwrites
rjsparks Jan 17, 2025
44a49ff
ci: use devblobstore container
rjsparks Jan 17, 2025
9d6b121
chore: identify places to write to blobstorage
rjsparks Jan 17, 2025
4eb6983
Merge remote-tracking branch 'ietf-tools/main' into feat/blobwrites
rjsparks Jan 22, 2025
9092b1b
chore: remove unreachable code
rjsparks Jan 24, 2025
430be28
Merge remote-tracking branch 'rjsparks/noglobunlink' into feat/blobwr…
rjsparks Jan 24, 2025
fa863af
feat: store materials
rjsparks Jan 24, 2025
c49293b
feat: store statements
rjsparks Jan 24, 2025
ff20013
feat: store status changes
rjsparks Jan 24, 2025
863d8ab
feat: store liaison attachments
rjsparks Jan 24, 2025
ec114a9
feat: store agendas provided with Interim session requests
rjsparks Jan 24, 2025
1848cd1
chore: capture TODOs
rjsparks Jan 25, 2025
ae63602
feat: store polls and chatlogs
rjsparks Jan 25, 2025
ce663e5
chore: remove unneeded TODO
rjsparks Jan 25, 2025
2454267
Merge remote-tracking branch 'ietf-tools/main' into feat/blobwrites
rjsparks Jan 25, 2025
be91813
feat: store drafts on submit and post
rjsparks Jan 27, 2025
6390205
fix: handle storage during doc expiration and resurrection
rjsparks Jan 27, 2025
2672de3
fix: mirror an unlink
rjsparks Jan 28, 2025
7065bf4
chore: add/refine TODOs
rjsparks Jan 28, 2025
2946cdb
feat: store slide submissions
rjsparks Jan 28, 2025
c904705
fix: structure slide test correctly
rjsparks Jan 28, 2025
6fac198
fix: correct sense of existence check
rjsparks Jan 28, 2025
90f04a9
feat: store some indexes
rjsparks Jan 28, 2025
790fa53
feat: BlobShadowFileSystemStorage
jennifer-richards Jan 28, 2025
4b170aa
feat: shadow floorplans / host logos to the blob
jennifer-richards Jan 29, 2025
a6bd585
chore: remove unused import
jennifer-richards Jan 29, 2025
53bfb80
feat: strip path from blob shadow names
jennifer-richards Jan 29, 2025
0857748
Merge remote-tracking branch 'upstream/feat/blobwrites' into imageblob
jennifer-richards Jan 29, 2025
5a9f18a
feat: shadow photos / thumbs
jennifer-richards Jan 29, 2025
d336ecc
refactor: combine photo and photothumb blob kinds
jennifer-richards Jan 29, 2025
476d504
style: whitespace
jennifer-richards Jan 29, 2025
a4eef7f
refactor: use kwargs consistently
jennifer-richards Jan 29, 2025
1e994cd
chore: migrations
jennifer-richards Jan 29, 2025
7ce4a3c
refactor: better deconstruct(); rebuild migrations
jennifer-richards Jan 29, 2025
3d4e230
feat: shadow image storage to blob store (#8477)
rjsparks Jan 29, 2025
dae85e8
fix: use new class in mack patch
rjsparks Jan 29, 2025
e6343ac
chore: add TODO
jennifer-richards Jan 29, 2025
7a7fe26
feat: store group index documents
rjsparks Jan 29, 2025
b0fba2a
chore: identify more TODO
rjsparks Jan 29, 2025
79a62e6
feat: store reviews
rjsparks Jan 30, 2025
6afe86e
Merge remote-tracking branch 'ietf-tools/main' into feat/blobwrites
rjsparks Jan 30, 2025
e287b89
Merge remote-tracking branch 'ietf-tools/main' into feat/blobwrites
rjsparks Jan 31, 2025
e22bac7
fix: repair merge
rjsparks Jan 31, 2025
2effb95
chore: remove unnecessary TODO
rjsparks Jan 31, 2025
78c94a6
feat: StoredObject metadata
rjsparks Feb 6, 2025
f5d59bc
fix: deburr some debugging code
rjsparks Feb 6, 2025
1f90170
fix: only set the deleted timestamp once
rjsparks Feb 11, 2025
9194b22
chore: correct typo
rjsparks Feb 11, 2025
9cf8c02
fix: get_or_create vs get and test
rjsparks Feb 11, 2025
0e40c52
fix: avoid the questionable is_seekable helper
rjsparks Feb 11, 2025
3721007
chore: capture future design consideration
rjsparks Feb 11, 2025
b932996
ci: merge feat/blobwrites into feat/blobs
rjsparks Feb 11, 2025
1578e3b
chore: blob store cfg for k8s
jennifer-richards Feb 12, 2025
abd1e76
chore: black
rjsparks Feb 13, 2025
a1c732f
chore: copyright
rjsparks Feb 13, 2025
d993fd5
ci: bucket name prefix option + run Black
jennifer-richards Feb 13, 2025
ac5f758
ci: fix typo in bucket name expression
jennifer-richards Feb 13, 2025
a10cb6d
chore: parameters in app-configure-blobstore
jennifer-richards Feb 13, 2025
6f9b461
ci: remove verify=False option
jennifer-richards Feb 14, 2025
19f2995
fix: don't return value from __init__
jennifer-richards Feb 14, 2025
892117f
feat: option to log timing of S3Storage calls
jennifer-richards Feb 14, 2025
4be1bdf
chore: units
jennifer-richards Feb 14, 2025
33281c5
fix: deleted->null when storing a file
jennifer-richards Feb 14, 2025
00f0a76
style: Black
jennifer-richards Feb 14, 2025
b99d73a
ci: Merge pull request #8537 from jennifer-richards/null-delete-on-write
rjsparks Feb 14, 2025
1cd3e34
ci: Merge remote-tracking branch 'ietf-tools/feat/blobs' into cleanup
rjsparks Feb 14, 2025
177018e
ci: Merge pull request #8530 from rjsparks/cleanup
rjsparks Feb 14, 2025
9000978
feat: log as JSON; refactor to share code; handle exceptions
jennifer-richards Feb 14, 2025
bd88352
Merge branch 'feat/blobs' into time-blobs
jennifer-richards Feb 14, 2025
c108727
ci: Merge pull request #8533 from jennifer-richards/time-blobs
rjsparks Feb 14, 2025
91824dd
ci: add ietf_log_blob_timing option for k8s
jennifer-richards Feb 14, 2025
b5ac102
test: --no-manage-blobstore option for running tests
jennifer-richards Feb 14, 2025
332dafc
test: use blob store settings from env, if set
jennifer-richards Feb 15, 2025
7130e3c
test: actually set a couple more storage opts
jennifer-richards Feb 15, 2025
dcad3e8
Merge pull request #8542 from jennifer-richards/optional-blobstore-mgmt
jennifer-richards Feb 15, 2025
34c3f5e
feat: offswitch (#8541)
rjsparks Feb 18, 2025
188fe2c
Merge branch 'main' into feat/blobs
jennifer-richards Feb 18, 2025
95d8455
chore: log timing of blob reads
jennifer-richards Feb 19, 2025
7c01d40
Merge pull request #8551 from jennifer-richards/time-blob-reads
jennifer-richards Feb 19, 2025
e1969b7
chore: import Config from botocore.config
jennifer-richards Feb 19, 2025
39ddc71
chore(deps): import boto3-stubs / botocore
jennifer-richards Feb 19, 2025
b0511af
chore: drop type annotation that mypy loudly ignores
jennifer-richards Feb 19, 2025
0642c66
refactor: add storage methods via mixin
jennifer-richards Feb 19, 2025
cadc466
feat: add timeout / retry limit to boto client
jennifer-richards Feb 19, 2025
9371a5f
ci: let k8s config the timeouts via env
jennifer-richards Feb 19, 2025
ece77d8
ci: Merge pull request #8552 from jennifer-richards/blob-types
rjsparks Feb 19, 2025
62fa5f3
ci: Merge branch 'feat/blobs' into boto-timeout
rjsparks Feb 19, 2025
881863b
ci: Merge pull request #8554 from jennifer-richards/boto-timeout
rjsparks Feb 19, 2025
15e2c94
chore: repair merge resolution typo
rjsparks Feb 19, 2025
8d4308b
chore: tweak settings imports
rjsparks Feb 19, 2025
a661280
chore: simplify k8s/settings_local.py imports
jennifer-richards Feb 19, 2025
41aa604
ci: Merge pull request #8555 from rjsparks/importflakes
rjsparks Feb 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .devcontainer/docker-compose.extend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ services:
# - datatracker-vscode-ext:/root/.vscode-server/extensions
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
network_mode: service:db
blobstore:
ports:
- '9000'
- '9001'

volumes:
datatracker-vscode-ext:
2 changes: 2 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
services:
db:
image: ghcr.io/ietf-tools/datatracker-db:latest
blobstore:
image: ghcr.io/ietf-tools/datatracker-devblobstore:latest

steps:
- uses: actions/checkout@v4
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ Nightly database dumps of the datatracker are available as Docker images: `ghcr.

> Note that to update the database in your dev environment to the latest version, you should run the `docker/cleandb` script.

### Blob storage for dev/test

The dev and test environments use [minio](https://github.com/minio/minio) to provide local blob storage. See the settings files for how the app container communicates with the blobstore container. If you need to work with minio directly from outside the containers (to interact with its api or console), use `docker compose` from the top level directory of your clone to expose it at an ephemeral port.

```
$ docker compose port blobstore 9001
0.0.0.0:<some ephemeral port>

$ curl -I http://localhost:<some ephemeral port>
HTTP/1.1 200 OK
...
```


The minio container exposes the minio api at port 9000 and the minio console at port 9001


### Frontend Development

#### Intro
Expand Down
23 changes: 22 additions & 1 deletion dev/deploy-to-container/settings_local.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright The IETF Trust 2007-2019, All Rights Reserved
# -*- coding: utf-8 -*-

from ietf.settings import * # pyflakes:ignore
from ietf.settings import * # pyflakes:ignore
from ietf.settings import STORAGES, MORE_STORAGE_NAMES, BLOBSTORAGE_CONNECT_TIMEOUT, BLOBSTORAGE_READ_TIMEOUT, BLOBSTORAGE_MAX_ATTEMPTS
import botocore.config

ALLOWED_HOSTS = ['*']

Expand Down Expand Up @@ -79,3 +81,22 @@

# OIDC configuration
SITE_URL = 'https://__HOSTNAME__'

for storagename in MORE_STORAGE_NAMES:
STORAGES[storagename] = {
"BACKEND": "ietf.doc.storage_backends.CustomS3Storage",
"OPTIONS": dict(
endpoint_url="http://blobstore:9000",
access_key="minio_root",
secret_key="minio_pass",
security_token=None,
client_config=botocore.config.Config(
signature_version="s3v4",
connect_timeout=BLOBSTORAGE_CONNECT_TIMEOUT,
read_timeout=BLOBSTORAGE_READ_TIMEOUT,
retries={"total_max_attempts": BLOBSTORAGE_MAX_ATTEMPTS},
),
verify=False,
bucket_name=f"test-{storagename}",
),
}
23 changes: 22 additions & 1 deletion dev/diff/settings_local.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright The IETF Trust 2007-2019, All Rights Reserved
# -*- coding: utf-8 -*-

from ietf.settings import * # pyflakes:ignore
from ietf.settings import * # pyflakes:ignore
from ietf.settings import STORAGES, MORE_STORAGE_NAMES, BLOBSTORAGE_CONNECT_TIMEOUT, BLOBSTORAGE_READ_TIMEOUT, BLOBSTORAGE_MAX_ATTEMPTS
import botocore.config

ALLOWED_HOSTS = ['*']

Expand Down Expand Up @@ -66,3 +68,22 @@
SLIDE_STAGING_PATH = 'test/staging/'

DE_GFM_BINARY = '/usr/local/bin/de-gfm'

for storagename in MORE_STORAGE_NAMES:
STORAGES[storagename] = {
"BACKEND": "ietf.doc.storage_backends.CustomS3Storage",
"OPTIONS": dict(
endpoint_url="http://blobstore:9000",
access_key="minio_root",
secret_key="minio_pass",
security_token=None,
client_config=botocore.config.Config(
signature_version="s3v4",
connect_timeout=BLOBSTORAGE_CONNECT_TIMEOUT,
read_timeout=BLOBSTORAGE_READ_TIMEOUT,
retries={"total_max_attempts": BLOBSTORAGE_MAX_ATTEMPTS},
),
verify=False,
bucket_name=f"test-{storagename}",
),
}
3 changes: 3 additions & 0 deletions dev/tests/docker-compose.debug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ services:
volumes:
- postgresdb-data:/var/lib/postgresql/data

blobstore:
image: ghcr.io/ietf-tools/datatracker-devblobstore:latest

volumes:
postgresdb-data:
23 changes: 22 additions & 1 deletion dev/tests/settings_local.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright The IETF Trust 2007-2019, All Rights Reserved
# -*- coding: utf-8 -*-

from ietf.settings import * # pyflakes:ignore
from ietf.settings import * # pyflakes:ignore
from ietf.settings import STORAGES, MORE_STORAGE_NAMES, BLOBSTORAGE_CONNECT_TIMEOUT, BLOBSTORAGE_READ_TIMEOUT, BLOBSTORAGE_MAX_ATTEMPTS
import botocore.config

ALLOWED_HOSTS = ['*']

Expand Down Expand Up @@ -65,3 +67,22 @@
SLIDE_STAGING_PATH = 'test/staging/'

DE_GFM_BINARY = '/usr/local/bin/de-gfm'

for storagename in MORE_STORAGE_NAMES:
STORAGES[storagename] = {
"BACKEND": "ietf.doc.storage_backends.CustomS3Storage",
"OPTIONS": dict(
endpoint_url="http://blobstore:9000",
access_key="minio_root",
secret_key="minio_pass",
security_token=None,
client_config=botocore.config.Config(
signature_version="s3v4",
connect_timeout=BLOBSTORAGE_CONNECT_TIMEOUT,
read_timeout=BLOBSTORAGE_READ_TIMEOUT,
retries={"total_max_attempts": BLOBSTORAGE_MAX_ATTEMPTS},
),
verify=False,
bucket_name=f"test-{storagename}",
),
}
10 changes: 10 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ services:
depends_on:
- db
- mq
- blobstore

ipc: host

Expand Down Expand Up @@ -83,6 +84,14 @@ services:
- .:/workspace
- app-assets:/assets

blobstore:
image: ghcr.io/ietf-tools/datatracker-devblobstore:latest
restart: unless-stopped
volumes:
- "minio-data:/data"



# Celery Beat is a periodic task runner. It is not normally needed for development,
# but can be enabled by uncommenting the following.
#
Expand All @@ -106,3 +115,4 @@ services:
volumes:
postgresdb-data:
app-assets:
minio-data:
4 changes: 2 additions & 2 deletions docker/app.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ RUN rm -rf /tmp/library-scripts
# Copy the startup file
COPY docker/scripts/app-init.sh /docker-init.sh
COPY docker/scripts/app-start.sh /docker-start.sh
RUN sed -i 's/\r$//' /docker-init.sh && chmod +x /docker-init.sh
RUN sed -i 's/\r$//' /docker-start.sh && chmod +x /docker-start.sh
RUN sed -i 's/\r$//' /docker-init.sh && chmod +rx /docker-init.sh
RUN sed -i 's/\r$//' /docker-start.sh && chmod +rx /docker-start.sh

# Fix user UID / GID to match host
RUN groupmod --gid $USER_GID $USERNAME \
Expand Down
27 changes: 24 additions & 3 deletions docker/configs/settings_local.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Copyright The IETF Trust 2007-2019, All Rights Reserved
# Copyright The IETF Trust 2007-2025, All Rights Reserved
# -*- coding: utf-8 -*-

from ietf.settings import * # pyflakes:ignore
from ietf.settings import * # pyflakes:ignore
from ietf.settings import STORAGES, MORE_STORAGE_NAMES, BLOBSTORAGE_CONNECT_TIMEOUT, BLOBSTORAGE_READ_TIMEOUT, BLOBSTORAGE_MAX_ATTEMPTS
import botocore.config

ALLOWED_HOSTS = ['*']

from ietf.settings_postgresqldb import DATABASES # pyflakes:ignore
from ietf.settings_postgresqldb import DATABASES # pyflakes:ignore

IDSUBMIT_IDNITS_BINARY = "/usr/local/bin/idnits"
IDSUBMIT_STAGING_PATH = "/assets/www6s/staging/"
Expand Down Expand Up @@ -37,6 +39,25 @@
# DEV_TEMPLATE_CONTEXT_PROCESSORS = [
# 'ietf.context_processors.sql_debug',
# ]
for storagename in MORE_STORAGE_NAMES:
STORAGES[storagename] = {
"BACKEND": "ietf.doc.storage_backends.CustomS3Storage",
"OPTIONS": dict(
endpoint_url="http://blobstore:9000",
access_key="minio_root",
secret_key="minio_pass",
security_token=None,
client_config=botocore.config.Config(
signature_version="s3v4",
connect_timeout=BLOBSTORAGE_CONNECT_TIMEOUT,
read_timeout=BLOBSTORAGE_READ_TIMEOUT,
retries={"total_max_attempts": BLOBSTORAGE_MAX_ATTEMPTS},
),
verify=False,
bucket_name=storagename,
),
}


DOCUMENT_PATH_PATTERN = '/assets/ietfdata/doc/{doc.type_id}/'
INTERNET_DRAFT_PATH = '/assets/ietf-ftp/internet-drafts/'
Expand Down
4 changes: 4 additions & 0 deletions docker/docker-compose.extend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ services:
pgadmin:
ports:
- '5433'
blobstore:
ports:
- '9000'
- '9001'
celery:
volumes:
- .:/workspace
Expand Down
28 changes: 28 additions & 0 deletions docker/scripts/app-configure-blobstore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env python
# Copyright The IETF Trust 2024, All Rights Reserved

import boto3
import os
import sys

from ietf.settings import MORE_STORAGE_NAMES


def init_blobstore():
blobstore = boto3.resource(
"s3",
endpoint_url=os.environ.get("BLOB_STORE_ENDPOINT_URL", "http://blobstore:9000"),
aws_access_key_id=os.environ.get("BLOB_STORE_ACCESS_KEY", "minio_root"),
aws_secret_access_key=os.environ.get("BLOB_STORE_SECRET_KEY", "minio_pass"),
aws_session_token=None,
config=botocore.config.Config(signature_version="s3v4"),
verify=False,
)
for bucketname in MORE_STORAGE_NAMES:
blobstore.create_bucket(
Bucket=f"{os.environ.get('BLOB_STORE_BUCKET_PREFIX', '')}{bucketname}".strip()
)


if __name__ == "__main__":
sys.exit(init_blobstore())
5 changes: 5 additions & 0 deletions docker/scripts/app-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ echo "Creating data directories..."
chmod +x ./docker/scripts/app-create-dirs.sh
./docker/scripts/app-create-dirs.sh

# Configure the development blobstore

echo "Configuring blobstore..."
PYTHONPATH=/workspace python ./docker/scripts/app-configure-blobstore.py

# Download latest coverage results file

echo "Downloading latest coverage results file..."
Expand Down
5 changes: 5 additions & 0 deletions ietf/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import debug # pyflakes:ignore

import ietf
from ietf.doc.storage_utils import retrieve_str
from ietf.doc.utils import get_unicode_document_content
from ietf.doc.models import RelatedDocument, State
from ietf.doc.factories import IndividualDraftFactory, WgDraftFactory, WgRfcFactory
Expand Down Expand Up @@ -553,6 +554,10 @@ def test_api_upload_polls_and_chatlog(self):
newdoc = session.presentations.get(document__type_id=type_id).document
newdoccontent = get_unicode_document_content(newdoc.name, Path(session.meeting.get_materials_path()) / type_id / newdoc.uploaded_filename)
self.assertEqual(json.loads(content), json.loads(newdoccontent))
self.assertEqual(
json.loads(retrieve_str(type_id, newdoc.uploaded_filename)),
json.loads(content)
)

def test_api_upload_bluesheet(self):
url = urlreverse("ietf.meeting.views.api_upload_bluesheet")
Expand Down
8 changes: 7 additions & 1 deletion ietf/doc/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
TelechatDocEvent, BallotPositionDocEvent, ReviewRequestDocEvent, InitialReviewDocEvent,
AddedMessageEvent, SubmissionDocEvent, DeletedEvent, EditedAuthorsDocEvent, DocumentURL,
ReviewAssignmentDocEvent, IanaExpertDocEvent, IRSGBallotDocEvent, DocExtResource, DocumentActionHolder,
BofreqEditorDocEvent, BofreqResponsibleDocEvent )
BofreqEditorDocEvent, BofreqResponsibleDocEvent, StoredObject )

from ietf.utils.validators import validate_external_resource_value

Expand Down Expand Up @@ -218,3 +218,9 @@ class DocExtResourceAdmin(admin.ModelAdmin):
search_fields = ['doc__name', 'value', 'display_name', 'name__slug',]
raw_id_fields = ['doc', ]
admin.site.register(DocExtResource, DocExtResourceAdmin)

class StoredObjectAdmin(admin.ModelAdmin):
list_display = ['store', 'name', 'modified', 'deleted']
list_filter = ['deleted']
search_fields = ['store', 'name', 'doc_name', 'doc_rev', 'deleted']
admin.site.register(StoredObject, StoredObjectAdmin)
14 changes: 14 additions & 0 deletions ietf/doc/expire.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from typing import List, Optional # pyflakes:ignore

from ietf.doc.storage_utils import exists_in_storage, remove_from_storage
from ietf.doc.utils import update_action_holders
from ietf.utils import log
from ietf.utils.mail import send_mail
Expand Down Expand Up @@ -156,11 +157,17 @@ def remove_ftp_copy(f):
if mark.exists():
mark.unlink()

def remove_from_active_draft_storage(file):
# Assumes the glob will never find a file with no suffix
ext = file.suffix[1:]
remove_from_storage("active-draft", f"{ext}/{file.name}", warn_if_missing=False)

# Note that the object is already in the "draft" storage.
src_dir = Path(settings.INTERNET_DRAFT_PATH)
for file in src_dir.glob("%s-%s.*" % (doc.name, rev)):
move_file(str(file.name))
remove_ftp_copy(str(file.name))
remove_from_active_draft_storage(file)

def expire_draft(doc):
# clean up files
Expand Down Expand Up @@ -218,6 +225,13 @@ def move_file_to(subdir):
mark = Path(settings.FTP_DIR) / "internet-drafts" / basename
if mark.exists():
mark.unlink()
if ext:
# Note that we're not moving these strays anywhere - the assumption
# is that the active-draft blobstore will not get strays.
# See, however, the note about "major system failures" at "unknown_ids"
blobname = f"{ext[1:]}/{basename}"
if exists_in_storage("active-draft", blobname):
remove_from_storage("active-draft", blobname)

try:
doc = Document.objects.get(name=filename, rev=revision)
Expand Down
Loading
Loading
0