Reject Git LFS Pushes When Namespace Storage Limits Are Exceeded
What does this MR do and why?
Reject git push
es that use LFS when namespace storage limits are exceeded.
Reject git LFS file locking requests.
Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/362951
How to set up and validate locally
Basic Setup
- Make sure the
automatic_purchased_storage_allocation
andenforce_namespace_storage_limit
application settings are both enabled (true
).
gitlabhq_development=# SELECT automatic_purchased_storage_allocation, enforce_namespace_storage_limit FROM application_settings;
automatic_purchased_storage_allocation | enforce_namespace_storage_limit
----------------------------------------+---------------------------------
t | t
(1 row)
gitlabhq_development=#
- Enable the
:namespace_storage_limit
,:enforce_storage_limit_for_paid
,:enforce_storage_limit_for_free
, and:namespace_storage_limit_bypass_date_check
feature flags in a rails console.
[1] pry(main)> Feature.enable(:namespace_storage_limit)
[...]
[2] pry(main)> Feature.enable(:enforce_storage_limit_for_paid)
[...]
[3] pry(main)> Feature.enable(:enforce_storage_limit_for_free)
[...]
[4] pry(main)> Feature.enable(:namespace_storage_limit_bypass_date_check)
[...]
[5] pry(main)>
- Apply the following patch to your local gitlab instance. This patch disables some caching around storage size and storage limits.
diff --git a/ee/app/models/ee/namespace/root_storage_size.rb b/ee/app/models/ee/namespace/root_storage_size.rb
index fd612db00ec..b37918bdfbc 100644
--- a/ee/app/models/ee/namespace/root_storage_size.rb
+++ b/ee/app/models/ee/namespace/root_storage_size.rb
@@ -26,16 +26,16 @@ def usage_ratio
end
def current_size
- @current_size ||= Rails.cache.fetch(['namespaces', root_namespace.id, CURRENT_SIZE_CACHE_KEY], expires_in: EXPIRATION_TIME) do
+ # @current_size ||= Rails.cache.fetch(['namespaces', root_namespace.id, CURRENT_SIZE_CACHE_KEY], expires_in: EXPIRATION_TIME) do
root_namespace.root_storage_statistics&.storage_size
- end
+ # end
end
def limit
- @limit ||= Rails.cache.fetch(['namespaces', root_namespace.id, LIMIT_CACHE_KEY], expires_in: EXPIRATION_TIME) do
+ # @limit ||= Rails.cache.fetch(['namespaces', root_namespace.id, LIMIT_CACHE_KEY], expires_in: EXPIRATION_TIME) do
root_namespace.actual_limits.storage_size_limit.megabytes +
root_namespace.additional_purchased_storage_size.megabytes
- end
+ # end
end
def remaining_storage_percentage
-
Restart your GDK simulating saas mode with
$ GITLAB_SIMULATE_SAAS=1 gdk start
. -
Setup a project using git LFS. Clone the repository. For this example, files with
*.iso
extensions will use LFS, and files with*.png
extensions will be able to use file locking. So you will want to run the following two commands while you setup LFS (these are the two commands in the examples in the documentation):
git lfs track "*.iso"
git lfs track "*.png" --lockable
- Navigate to your project's group page. In the example here, my project is "Storage LFS Project" under the "Storage Test Group" group so I navigate to the "Storage Test Group" page, pictured below.
Navigate to Settings > Usage Quotas. Click the Storage tab. You can see how much total namespace storage you currently have here.
This can give you a good idea of what number to use in the SQL UPDATE
statements in the following steps.
- Find the
plan_limit.id
of your localplan_limit
for thefree
plan. (The project in these examples is in a group on the free plan. You may need to use a different plan if your project is on an Ultimate or Premium plan.)
gitlabhq_development=# SELECT p.id, p.name, p.title, l.id, l.storage_size_limit FROM plans AS p JOIN plan_limits AS l ON p.id = l.plan_id;
id | name | title | id | storage_size_limit
----+----------------+---------------------------+----+--------------------
1 | default | Default | 1 | 0
2 | bronze | Bronze | 6 | 0
3 | silver | Silver | 7 | 0
4 | gold | Gold | 8 | 0
5 | free | | 5 | 30
6 | premium | Premium (Formerly Silver) | 23 | 0
7 | ultimate | Ultimate (Formerly Gold) | 26 | 0
8 | ultimate_trial | Ultimate Trial | 3 | 0
9 | premium_trial | Premium Trial | 4 | 0
10 | opensource | Open Source Program | 28 | 0
(10 rows)
gitlabhq_development=#
Make sure that the storage_size_limit
for the free
plan is either 0
or larger than your namespace storage size.
Verify LFS pushes are rejected
- Create a new branch. Add an iso file to the branch. Commit the file and push the branch.
$ git checkout -b add-pictures
Switched to a new branch 'add-pictures'
$ echo 'some data' > file.iso
$ git add file.iso
$ git commit -m 'Add an iso file'
[add-pictures 415fada] Add an iso file
1 file changed, 3 insertions(+)
create mode 100644 file.iso
$ git push -u local-gitlab add-pictures
Uploading LFS objects: 100% (1/1), 10 B | 0 B/s, done.
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 375 bytes | 375.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for add-pictures, visit:
remote: http://local-gitlab:3000/storage-test-group/storage-lfs-project/-/merge_requests/new?merge_request%5Bsource_branch%5D=add-pictures
remote:
To ssh://127.0.0.1:2222/storage-test-group/storage-lfs-project.git
* [new branch] add-pictures -> add-pictures
branch 'add-pictures' set up to track 'local-gitlab/add-pictures'.
$
- Update your local plan limits for the
free
plan. Pick a value under the total namespace storage. Your id may be different than the one seen below.
gitlabhq_development=# UPDATE plan_limits SET storage_size_limit = 3 WHERE id = 5;
UPDATE 1
gitlabhq_development=#
- Update the iso file. Try
git push
. The push is rejected.
$ echo 'more data' >> file.iso
$ git add file.iso
$ git commit -m 'Update iso file'
[add-pictures fd4a3e6] Update iso file
1 file changed, 2 insertions(+), 2 deletions(-)
$ git push
Remote "local-gitlab" does not support the Git LFS locking API. Consider disabling it with:
$ git config lfs.https://127.0.0.1/storage-test-group/storage-lfs-project.git/info/lfs.locksverify false
Your push to this repository has been rejected because the namespace storage limit of 3 MB has been reached. Reduce your namespace storage or purchase additional storage.
error: failed to push some refs to 'ssh://127.0.0.1:2222/storage-test-group/storage-lfs-project.git'
$
Verify that LFS locks are rejected
- Update the storage limit. Pick a number over the total namespace storage.
gitlabhq_development=# UPDATE plan_limits SET storage_size_limit = 30 WHERE id = 5;
UPDATE 1
gitlabhq_development=#
- Add two new
.png
files -cat.png
anddog.png
. Commit and push them. Lockcat.png
.
$ echo 'data' > cat.png
$ git add cat.png
$ git commit -m 'Add cat picture'
[add-pictures ef3ab92] Add cat picture
1 file changed, 3 insertions(+)
create mode 100644 cat.png
$ git push
Uploading LFS objects: 100% (1/1), 5 B | 0 B/s, done.
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 373 bytes | 373.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for add-pictures, visit:
remote: http://local-gitlab:3000/storage-test-group/storage-lfs-project/-/merge_requests/new?merge_request%5Bsource_branch%5D=add-pictures
remote:
To ssh://127.0.0.1:2222/storage-test-group/storage-lfs-project.git
9acf2f3..ef3ab92 add-pictures -> add-pictures
$ echo 'other data' > dog.png
$ git add dog.png
$ git commit -m 'Add dog picture'
[add-pictures 2135e80] Add dog picture
1 file changed, 3 insertions(+)
create mode 100644 dog.png
$ git push
Uploading LFS objects: 100% (1/1), 11 B | 0 B/s, done.
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 377 bytes | 377.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for add-pictures, visit:
remote: http://local-gitlab:3000/storage-test-group/storage-lfs-project/-/merge_requests/new?merge_request%5Bsource_branch%5D=add-pictures
remote:
To ssh://127.0.0.1:2222/storage-test-group/storage-lfs-project.git
ef3ab92..2135e80 add-pictures -> add-pictures
$ git lfs lock cat.png
Locked cat.png
$ git lfs locks
cat.png Stan Smith ID:5
$
- Update the storage limit. Pick a number under the total namespace storage.
gitlabhq_development=# UPDATE plan_limits SET storage_size_limit = 3 WHERE id = 5;
UPDATE 1
gitlabhq_development=#
- Try to lock
dog.png
. Verify that the lock is rejected.
$ git lfs lock dog.png
Locking dog.png failed: Your push to this repository has been rejected because the namespace storage limit of 3 MB has been reached. Reduce your namespace storage or purchase additional storage.
$ git lfs locks
cat.png Stan Smith ID:5
$
- Verify that attempting to unlock
cat.png
is rejected.
$ git lfs unlock cat.png
Your push to this repository has been rejected because the namespace storage limit of 3 MB has been reached. Reduce your namespace storage or purchase additional storage.
$ git lfs locks
cat.png Stan Smith ID:5
$
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.