Skip to content

Commit

Permalink
CMR-9257: Publish drafts and delete them from database and elastic se…
Browse files Browse the repository at this point in the history
…arch.
  • Loading branch information
siwei xu authored and siwei xu committed Sep 7, 2023
1 parent 60820e6 commit f47f519
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 2 deletions.
124 changes: 124 additions & 0 deletions ingest-app/src/cmr/ingest/api/generic_documents.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,24 @@
[cmr.common.services.errors :as errors]
[cmr.common.util :as util :refer [defn-timed]]
[cmr.ingest.api.core :as api-core]
[cmr.ingest.api.collections :as collections]
[cmr.ingest.api.services :as services]
[cmr.ingest.api.tools :as tools]
[cmr.ingest.api.variables :as variables]
[cmr.schema-validation.json-schema :as js-validater]
[cmr.transmit.metadata-db :as mdb]
[cmr.transmit.metadata-db2 :as mdb2]
[cmr.umm-spec.umm-spec-core :as spec]))

(defn string->stream
"Used to construct request body using the metadata string
retrieved from database when publishing a draft concept."
([s] (string->stream s "UTF-8"))
([s encoding]
(-> s
(.getBytes encoding)
(java.io.ByteArrayInputStream.))))

(defn disabled-for-ingest?
"Determine if a generic schema is disabled for ingest
Parameters:
Expand Down Expand Up @@ -235,6 +248,117 @@
request-context :read :provider-object provider-id))]
(api-core/delete-concept concept-type provider-id native-id request)))

(defn- extract-info-from-concept-id
"Extract concept info from concept-id."
[concept-id]
(let [draft-concept-type (common-concepts/concept-id->type concept-id)
provider-id (common-concepts/concept-id->provider-id concept-id)
;; get the concept type of the document that is contained in the draft
;; :collection is the concept type of the document that is contained in :collection-draft
concept-type-in-draft (common-concepts/get-concept-type-of-draft draft-concept-type)]
{:draft-concept-type draft-concept-type
:provider-id provider-id
:concept-type-in-draft concept-type-in-draft}))

(defn- get-info-from-metadata-db
"Get information from metadata db."
[request concept-id provider-id concept-type]
(let [content-type-passed-in (:content-type request)
context (:request-context request)
search-result (mdb/get-latest-concept context concept-id)
draft-native-id (:native-id search-result)
metadata (:metadata search-result)
format (:format search-result)
_ (when-not (and metadata format)
(errors/throw-service-error
:bad-request
(format "Concept-id [%s] does not exist." concept-id)))
content-type (if content-type-passed-in
content-type-passed-in
format)
body (string->stream metadata)
request (-> request
(assoc :body body :content-type content-type)
(assoc-in [:headers "content-type"] content-type)
(assoc-in [:route-params :provider-id] provider-id)
(assoc-in [:params :provider-id] provider-id)
(assoc-in [:route-params :concept-type] concept-type)
(assoc-in [:params :concept-type] concept-type))]
{:native-id draft-native-id
:request request}))

(defn publish-non-variable-draft
"Publish a non-variable draft concept. i.e. Ingest the corresponding concept
and delete the draft."
[request concept-id native-id]
(let [{:keys [draft-concept-type provider-id concept-type-in-draft]}
(extract-info-from-concept-id concept-id)]
;; If draft-concept-type is not a non-variable draft, throw error.
(when-not (and (common-concepts/is-draft-concept? draft-concept-type)
(not= :variable-draft draft-concept-type))
(errors/throw-service-error
:bad-request
(format "Only non-variable draft can be published in this route. concept-id [%s] does not belong to a non-variable draft concept" concept-id)))

;;Get info from metadata-db.
(let [info (get-info-from-metadata-db request concept-id provider-id concept-type-in-draft)
request (:request info)
draft-native-id (:native-id info)
;;publish the concept-type-in-draft
publish-result (case concept-type-in-draft
:collection (collections/ingest-collection provider-id native-id request)
:tool (tools/ingest-tool provider-id native-id request)
:service (services/ingest-service provider-id native-id request)
(create-generic-document request))]
(if (= 201 (:status publish-result))
;;construct request to delete the draft.
(let [delete-request (-> request
(assoc-in [:route-params :native-id] draft-native-id)
(assoc-in [:route-params :concept-type] draft-concept-type)
(assoc-in [:params :native-id] draft-native-id)
(assoc-in [:params :concept-type] draft-concept-type))
delete-result (delete-generic-document delete-request)]
(if (= 200 (:status delete-result))
publish-result
(errors/throw-service-error
:bad-request
(format "Publishing draft is successful with info [%s]. Deleting draft failed with info [%s]."
(:body publish-result) (:body delete-result)))))
publish-result))))

(defn publish-variable-draft
"Publish a variable draft concept. i.e. Ingest the corresponding variable and
delete the variable draft."
[provider-id native-id request coll-concept-id coll-revision-id var-draft-id]
(let [{:keys [draft-concept-type provider-id concept-type-in-draft]}
(extract-info-from-concept-id var-draft-id) ]
;; If concept-id is not a variable draft, throw error.
(when-not (= :variable-draft draft-concept-type)
(errors/throw-service-error
:bad-request
(format "Only variable draft can be published in this route. concept-id [%s] does not belong to a variable draft concept" var-draft-id)))

;; Get information from metadata-db.
(let [info (get-info-from-metadata-db request var-draft-id provider-id concept-type-in-draft)
request (:request info)
draft-native-id (:native-id info)
publish-result (variables/ingest-variable provider-id native-id request coll-concept-id coll-revision-id)]
(if (= 201 (:status publish-result))
;;construct request to delete the draft.
(let [delete-request (-> request
(assoc-in [:route-params :native-id] draft-native-id)
(assoc-in [:route-params :concept-type] draft-concept-type)
(assoc-in [:params :native-id] draft-native-id)
(assoc-in [:params :concept-type] draft-concept-type))
delete-result (delete-generic-document delete-request)]
(if (= 200 (:status delete-result))
publish-result
(errors/throw-service-error
:bad-request
(format "Publishing draft is successful with info [%s]. Deleting draft failed with info [%s]."
(:body publish-result) (:body delete-result)))))
publish-result))))

(defn crud-generic-document
"This function checks for required parameters. If they don't exist then throw an error, otherwise send the request
on to the corresponding function."
Expand Down
20 changes: 20 additions & 0 deletions ingest-app/src/cmr/ingest/api/routes.clj
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,37 @@

(def ingest-routes
(routes
;; publish non-variable draft routes
(api-core/set-default-error-format
:xml
(context "/publish/:draft-id" [draft-id]
(context "/:native-id" [native-id]
(PUT "/"
request
(gen-doc/publish-non-variable-draft request draft-id native-id)))))
;; variable ingest routes with association
(api-core/set-default-error-format
:xml
(context "/collections/:coll-concept-id" [coll-concept-id]
(context "/:coll-revision-id" [coll-revision-id]
(context "/variables/:native-id" [native-id]
;; publish variable draft
(context "/publish/:var-draft-id" [var-draft-id]
(PUT "/"
request
(gen-doc/publish-variable-draft
nil native-id request coll-concept-id coll-revision-id var-draft-id)))
(PUT "/"
request
(variables/ingest-variable
nil native-id request coll-concept-id coll-revision-id))))
(context "/variables/:native-id" [native-id]
;; publish variable draft
(context "/publish/:var-draft-id" [var-draft-id]
(PUT "/"
request
(gen-doc/publish-variable-draft
nil native-id request coll-concept-id nil var-draft-id)))
(PUT "/"
request
(variables/ingest-variable
Expand Down
10 changes: 10 additions & 0 deletions system-int-test/src/cmr/system_int_test/utils/generic_util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
(slurp)
(json/parse-string true)))

(def order-option-draft (-> "schemas/order-option-draft/v1.0.0/metadata.json"
(jio/resource)
(slurp)
(json/parse-string true)))

(def variable-draft (-> "schemas/variable-draft/v1.0.0/metadata.json"
(jio/resource)
(slurp)
(json/parse-string true)))

(defn grant-all-drafts-fixture
"A test fixture that grants all users the ability to create and modify drafts."
[providers guest-permissions registered-permissions]
Expand Down
40 changes: 40 additions & 0 deletions system-int-test/src/cmr/system_int_test/utils/ingest_util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,46 @@
params (merge params (when accept-format {:accept accept-format}))]
(parse-ingest-response (client/request params) options))))

(defn publish-non-variable-draft
"Publish a non-variable draft and return a map with status, concept-id, and revision-id"
[draft-concept-id native-id options]
(let [{:keys [token client-id user-id validate-keywords validate-umm-c cmr-request-id x-request-id test-existing-errors]} options
method (get options :method :put)
headers (util/remove-nil-keys {"Cmr-Validate-Keywords" validate-keywords
"Cmr-Validate-Umm-C" validate-umm-c
"Cmr-Test-Existing-Errors" test-existing-errors
"Authorization" token
"User-Id" user-id
"Client-Id" client-id
"CMR-Request-Id" cmr-request-id
"X-Request-Id" x-request-id})
params {:method method
:url (url/publish-non-variable-draft-url draft-concept-id native-id)
:headers headers
:throw-exceptions false
:connection-manager (s/conn-mgr)}]
(parse-ingest-response (client/request params) options)))

(defn publish-variable-draft
"Publish a variable draft."
[coll-id coll-revision-id native-id variable-draft-id options]
(let [{:keys [token client-id user-id validate-keywords validate-umm-c cmr-request-id x-request-id test-existing-errors]} options
method (get options :method :put)
headers (util/remove-nil-keys {"Cmr-Validate-Keywords" validate-keywords
"Cmr-Validate-Umm-C" validate-umm-c
"Cmr-Test-Existing-Errors" test-existing-errors
"Authorization" token
"User-Id" user-id
"Client-Id" client-id
"CMR-Request-Id" cmr-request-id
"X-Request-Id" x-request-id})
params {:method method
:url (url/publish-variable-draft-url coll-id coll-revision-id native-id variable-draft-id)
:headers headers
:throw-exceptions false
:connection-manager (s/conn-mgr)}]
(parse-ingest-response (client/request params) options)))

;; Temporary function, this calls the subscription routes under the ingest root url, will be removed in CMR-8270
(defn ingest-subscription-concept
"Ingest a concept and return a map with status, concept-id, and revision-id"
Expand Down
22 changes: 22 additions & 0 deletions system-int-test/src/cmr/system_int_test/utils/url_helper.clj
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@
(str url "/" (codec/url-encode native-id))
url))))

(defn publish-non-variable-draft-url
[draft-concept-id native-id]
(format "http://localhost:%s/publish/%s/%s"
(transmit-config/ingest-port)
(codec/url-encode draft-concept-id)
(codec/url-encode native-id)))

(defn ingest-subscription-url
([]
(ingest-subscription-url nil))
Expand All @@ -239,6 +246,21 @@
(codec/url-encode coll-id)
(codec/url-encode native-id)))))

(defn publish-variable-draft-url
[coll-id coll-revision-id native-id variable-draft-id]
(if coll-revision-id
(format "http://localhost:%s/collections/%s/%s/variables/%s/publish/%s"
(transmit-config/ingest-port)
(codec/url-encode coll-id)
(codec/url-encode coll-revision-id)
(codec/url-encode native-id)
(codec/url-encode variable-draft-id))
(format "http://localhost:%s/collections/%s/variables/%s/publish/%s"
(transmit-config/ingest-port)
(codec/url-encode coll-id)
(codec/url-encode native-id)
(codec/url-encode variable-draft-id))))

(defn validate-url
[provider-id type native-id]
(format "http://localhost:%s/providers/%s/validate/%s/%s"
Expand Down
Loading

0 comments on commit f47f519

Please sign in to comment.