Skip to content

Commit b7d7d99

Browse files
committed
Properly delete artifacts from s3
We have admin functionality to delete artifacts from the repo that we use rarely. This code had a bug where it would not delete from the s3 repo. This was because the s3-client assumes that a string path that does not end in / is a single object, and the presence of the / means we need to delete multiple objects. The admin delete code was generating a path that did not end in /, but assumed that the s3-client would delete everything under that path. This fixes that issue by generating a path with a trailing /, and expands the admin deletion test to test against s3. Fixes #881.
1 parent 662e10f commit b7d7d99

File tree

4 files changed

+59
-22
lines changed

4 files changed

+59
-22
lines changed

src/clojars/admin.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
(defn segments->path [segments]
4747
(let [[group & rest] (remove nil? segments)]
48-
(str/join "/" (concat [(fu/group->path group)] rest))))
48+
(str (str/join "/" (concat [(fu/group->path group)] rest)) "/")))
4949

5050
(defn help []
5151
(println

test/clojars/test_helper.clj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
[clojure.java.shell :as shell]
1818
[clojure.string :as str]
1919
[clojure.test :refer [is]]
20+
[cognitect.aws.client.api :as aws]
2021
[com.stuartsierra.component :as component]
2122
[matcher-combinators.test])
2223
(:import
@@ -208,3 +209,18 @@
208209
(defn assert-status
209210
[session status]
210211
(is (= status (get-in session [:response :status]))))
212+
213+
(defn real-s3-client
214+
"This creates a real s3 client for testing s3-specific functionality. It
215+
requires minio to running. See docker-compose.yml."
216+
[bucket]
217+
(let [client (s3/s3-client bucket
218+
{:credentials {:access-key-id "fake-access-key"
219+
:secret-access-key "fake-secret-key"}
220+
:endpoint {:protocol "http"
221+
:hostname "localhost"
222+
:port 9000}
223+
:region "us-east-1"})]
224+
(aws/invoke (:s3 client) {:op :CreateBucket
225+
:request {:Bucket bucket}})
226+
client))

test/clojars/unit/admin_test.clj

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[clojars.admin :as admin]
44
[clojars.config :refer [config]]
55
[clojars.db :as db]
6+
[clojars.s3 :as s3]
67
[clojars.search :as search]
78
[clojars.storage :as storage]
89
[clojars.test-helper :as help]
@@ -12,17 +13,27 @@
1213

1314
(def ^:dynamic *search-removals* nil)
1415

15-
(defn with-repo-setup2
16+
(def ^:dynamic *s3-client* nil)
17+
18+
;; Note: these tests exercise the s3 client end-to-end, and require minio to
19+
;; running. See docker-compose.yml
20+
21+
(defn with-repo-setup
1622
[f]
17-
(let [jar (io/file (io/resource "fake.jar"))]
23+
(let [config (config)
24+
jar (io/file (io/resource "fake.jar"))
25+
s3-client (help/real-s3-client (get-in config [:s3 :repo-bucket]))]
1826
(binding [*search-removals* (atom #{})
27+
*s3-client* s3-client
1928
admin/*db* help/*db*
2029
admin/*search* (reify search/Search
2130
(delete! [_ group#]
2231
(swap! *search-removals* conj group#))
2332
(delete! [_ group# artifact#]
2433
(swap! *search-removals* conj (format "%s/%s" group# artifact#))))
25-
admin/*storage* (storage/fs-storage (:repo (config)))]
34+
admin/*storage* (storage/multi-storage
35+
(storage/fs-storage (:repo config))
36+
(storage/s3-storage s3-client))]
2637
(db/add-user admin/*db* "testuser@example.com" "testuser" "password")
2738
(help/add-verified-group "testuser" "org.ham")
2839
(db/add-jar admin/*db* "testuser" {:group "org.ham" :name "biscuit" :version "1" :description "delete me"})
@@ -41,14 +52,14 @@
4152
(use-fixtures :each
4253
help/default-fixture
4354
help/with-clean-database
44-
with-repo-setup2)
55+
with-repo-setup)
4556

4657
(deftest segments->path-should-work
4758
(are [exp given] (= exp (admin/segments->path given))
48-
"a/b" ["a" "b"]
49-
"a/b/c" ["a.b" "c"]
50-
"a/b/c" ["a.b.c"]
51-
"a/b/c" ["a.b" nil "c" nil]))
59+
"a/b/" ["a" "b"]
60+
"a/b/c/" ["a.b" "c"]
61+
"a/b/c/" ["a.b.c"]
62+
"a/b/c/" ["a.b" nil "c" nil]))
5263

5364
(deftest backup-dir-should-work
5465
(with-redefs [admin/current-date-str (constantly "20160827")]
@@ -71,6 +82,13 @@
7182
(is (backup-exists? "org/ham" "sandwich/1/sandwich-1.jar"))
7283
(is (backup-exists? "org/ham" "sandwich/1/sandwich-1.pom"))
7384

85+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/1/biscuit-1.jar")))
86+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/1/biscuit-1.pom")))
87+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/2/biscuit-2.jar")))
88+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/2/biscuit-2.pom")))
89+
(is (not (s3/object-exists? *s3-client* "org/ham/sandwich/1/sandwich-1.jar")))
90+
(is (not (s3/object-exists? *s3-client* "org/ham/sandwich/1/sandwich-1.pom")))
91+
7492
(is (not (.exists (io/file (:repo (config)) "org/ham"))))
7593

7694
(is (not (db/find-jar admin/*db* "org.ham" "biscuit")))
@@ -96,6 +114,13 @@
96114
(is (.exists (io/file (:repo (config)) "org/ham/sandwich/1/sandwich-1.jar")))
97115
(is (.exists (io/file (:repo (config)) "org/ham/sandwich/1/sandwich-1.pom")))
98116

117+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/1/biscuit-1.jar")))
118+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/1/biscuit-1.pom")))
119+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/2/biscuit-2.jar")))
120+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/2/biscuit-2.pom")))
121+
(is (s3/object-exists? *s3-client* "org/ham/sandwich/1/sandwich-1.jar"))
122+
(is (s3/object-exists? *s3-client* "org/ham/sandwich/1/sandwich-1.pom"))
123+
99124
(is (not (db/find-jar admin/*db* "org.ham" "biscuit")))
100125
(is (db/find-jar admin/*db* "org.ham" "sandwich"))
101126
(is (seq (db/group-activenames admin/*db* "org.ham")))
@@ -119,6 +144,13 @@
119144
(is (.exists (io/file (:repo (config)) "org/ham/sandwich/1/sandwich-1.jar")))
120145
(is (.exists (io/file (:repo (config)) "org/ham/sandwich/1/sandwich-1.pom")))
121146

147+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/1/biscuit-1.jar")))
148+
(is (not (s3/object-exists? *s3-client* "org/ham/biscuit/1/biscuit-1.pom")))
149+
(is (s3/object-exists? *s3-client* "org/ham/biscuit/2/biscuit-2.jar"))
150+
(is (s3/object-exists? *s3-client* "org/ham/biscuit/2/biscuit-2.pom"))
151+
(is (s3/object-exists? *s3-client* "org/ham/sandwich/1/sandwich-1.jar"))
152+
(is (s3/object-exists? *s3-client* "org/ham/sandwich/1/sandwich-1.pom"))
153+
122154
(is (not (db/find-jar admin/*db* "org.ham" "biscuit" "1")))
123155
(is (db/find-jar admin/*db* "org.ham" "biscuit" "2"))
124156
(is (db/find-jar admin/*db* "org.ham" "sandwich"))

test/clojars/unit/s3_test.clj

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns clojars.unit.s3-test
22
(:require
33
[clojars.s3 :as s3]
4+
[clojars.test-helper :as help]
45
[clojure.java.io :as io]
56
[clojure.test :refer [deftest is testing use-fixtures]]
67
[cognitect.aws.client.api :as aws]
@@ -17,19 +18,7 @@
1718
v))
1819

1920
(def ^:private real-s3-client
20-
(memoize
21-
(fn []
22-
(let [bucket "testing-bucket"
23-
client (s3/s3-client bucket
24-
{:credentials {:access-key-id "fake-access-key"
25-
:secret-access-key "fake-secret-key"}
26-
:endpoint {:protocol "http"
27-
:hostname "localhost"
28-
:port 9000}
29-
:region "us-east-1"})]
30-
(aws/invoke (:s3 client) {:op :CreateBucket
31-
:request {:Bucket bucket}})
32-
client))))
21+
(memoize (fn [] (help/real-s3-client "testing-bucket"))))
3322

3423
(def ^:private page-size 1000)
3524

0 commit comments

Comments
 (0)