From f796373d7de201c0a46f06b3155b1734b9872bb3 Mon Sep 17 00:00:00 2001 From: Adrian Batos-Parac Date: Thu, 12 Apr 2018 15:31:45 -0400 Subject: Fix graphwalk capabilities Fixes the issue where graphwalk was not working properly in the chameleon code within ONAP. Change-Id: Iae1dd036f10ab6443a40cac66ae69fad77036cb2 Issue-ID: AAI-797 Signed-off-by: Adrian Batos-Parac --- .gitignore | 95 +++++++++++++++++++++++++++++++++++++++++ project.clj | 2 +- src/chameleon/aai_processor.clj | 58 ++++++++++++++++++++----- src/chameleon/event.clj | 9 ++-- src/chameleon/handler.clj | 22 +++++++--- src/chameleon/route.clj | 41 +++++++++--------- 6 files changed, 188 insertions(+), 39 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d39b07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,95 @@ +# Created by https://www.gitignore.io/api/clojure,emacs,osx,java + +### Clojure ### +pom.xml +pom.xml.asc +*jar +lib/ +classes/ +target/ +out/ +checkouts/ +.lein-deps-sum +.lein-repl-history +.lein-plugins/ +.lein-failures +.nrepl-port +logs/ +debug-logs/ + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ + + +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Java ### +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* diff --git a/project.clj b/project.clj index aaab854..044856b 100644 --- a/project.clj +++ b/project.clj @@ -13,7 +13,7 @@ [integrant "0.6.2"] [clojure-future-spec "1.9.0-beta4"] [yogthos/config "0.9"] - [org.onap.aai.event-client/event-client-dmaap "1.2.0"] + [org.onap.aai.event-client/event-client-dmaap "1.2.1"] ] :repositories [["onap-releases" {:url "https://nexus.onap.org/content/repositories/releases/"}] ["onap-public" {:url "https://nexus.onap.org/content/repositories/public/"}] diff --git a/src/chameleon/aai_processor.clj b/src/chameleon/aai_processor.clj index c709ed1..7025c31 100644 --- a/src/chameleon/aai_processor.clj +++ b/src/chameleon/aai_processor.clj @@ -1,26 +1,64 @@ (ns chameleon.aai-processor (:require [chameleon.txform :refer :all] [chameleon.route :refer :all] - [cheshire.core :refer :all])) + [cheshire.core :refer :all] + [clojure.set :refer :all])) + +(defn- gen-trim-relationship + "Generates a trimmed down version of the relationship containing only the id, type, url, and target" + [relationship] + (let [id (relationship"_id") + type (get-in relationship ["properties" "type"]) + src-id (get-in relationship ["source" "id"]) + src-type (get-in relationship ["source" "type"]) + target-id (get-in relationship ["target" "id"]) + target-type (get-in relationship ["target" "type"])] + {"id" id + "type" type + "source" {"id" src-id "type" src-type} + "target" {"id" target-id "type" target-type}}) + ) (defn from-gallifrey "Transforms Gallifrey response payloads into a format consumable by AAI-centric clients" [body] - (->> body - (map (fn [[k v]] [(clojure.string/split k #"\.") v])) - ((fn [x] (reduce #(assoc-in %1 (first %2) (second %2) ) {} x))))) + (let [resource-type (get-in body ["properties" "_type"]) + id (body "_id") + type (get-in body ["properties" "type"]) + properties (body "properties") + entity-response { + "id" id + "type" type + "properties" (dissoc properties "_type" "type") + }] + (if (= resource-type "entity") + ; Transform into an entity type + (let [relationships (body "relationships")] + (assoc entity-response + "in" (into [] (map gen-trim-relationship (filter #(= (get-in % ["target" "id"]) id) relationships))) + "out" (into [] (map gen-trim-relationship (filter #(= (get-in % ["source" "id"]) id) relationships))))) + entity-response))) (defn from-spike "Transforms Spike-based event payloads to a format accepted by Gallifrey for vertices and relationships" [gallifrey-host payload] (let [txpayload (map-keywords (parse-string payload)) operation (:operation txpayload) + parse-type (if (contains? txpayload :vertex) + :vertex + :relationship) entity-type (if (contains? txpayload :vertex) - :vertex + :entity :relationship) - entity (map-keywords (entity-type txpayload)) + entity (map-keywords (parse-type txpayload)) key (:key entity) - properties (assoc (:properties entity) :type (:type entity))] - (assert-gallifrey gallifrey-host "aai" (if (= entity-type :vertex) - {:meta {:key key :operation operation} :body (generate-string properties)} - {:meta {:key key :operation operation} :body (generate-string (conj properties (flatten-entry entity :source) (flatten-entry entity :target)))})))) + properties (assoc (:properties entity) :type (:type entity)) + truth-time (:truth-time entity) + entity-assertion {:meta {:key key + :operation operation + :time {:t-t truth-time}}}] + (assert-gallifrey gallifrey-host "aai" (name entity-type) (if (= entity-type :entity) + (assoc entity-assertion :body (generate-string {:properties properties})) + (assoc entity-assertion :body (generate-string (conj {:properties properties} + {:source (rename-keys (:source entity) {"key" "id"})} + {:target (rename-keys (:target entity) {"key" "id"})}))))))) diff --git a/src/chameleon/event.clj b/src/chameleon/event.clj index 8201acb..2b32d26 100644 --- a/src/chameleon/event.clj +++ b/src/chameleon/event.clj @@ -1,7 +1,8 @@ (ns chameleon.event (:require [chameleon.txform] [chameleon.route] - [integrant.core :as ig]) + [integrant.core :as ig] + [clojure.string :refer [starts-with?]]) (:import [org.onap.aai.event.client DMaaPEventConsumer])) (defmethod ig/init-key :chameleon/event @@ -13,6 +14,8 @@ (let [it (.iterator (.consume event-processor))] (println "Polling...") (while (.hasNext it) - (let [event (.next it)] - (processor gallifrey-host event)))))))) + (try (let [event (.next it)] + (if (not (starts-with? event "DMAAP")) ;Temporarily added for current version of dmaap client + (processor gallifrey-host event))) + (catch Exception e (println (str "Unexpected exception during processing: " (.getMessage e))))))))))) )) diff --git a/src/chameleon/handler.clj b/src/chameleon/handler.clj index 7a4a5fe..2a4c0f7 100644 --- a/src/chameleon/handler.clj +++ b/src/chameleon/handler.clj @@ -26,20 +26,32 @@ (declare serialize de-serialize) -(defresource entity-endpoint [id] +(defresource resource-endpoint [type id] :allowed-methods [:get] :available-media-types ["application/json"] :exists? (fn [ctx] - (let [resource (-> (c-route/query @g-host id (-> ctx :request :params :t-k)))] + (let [resource (c-route/query @g-host id type (-> ctx + :request + :params + (select-keys [:t-t :t-k])))] ; Only pass through the allowable set of keys (when (= (:status resource) 200) - {::resource (-> resource :body json/parse-string (dissoc "_meta") (chameleon.aai-processor/from-gallifrey))}))) + {::resource (-> resource + :body + json/parse-string + (dissoc "_meta") + (chameleon.aai-processor/from-gallifrey))}))) :existed? (fn [ctx] - (when-let [status (-> (c-route/query @g-host id (-> ctx :request :params :t-k)) :status)] + (when-let [status (-> (c-route/query @g-host id type (-> ctx + :request + :params + (select-keys [:t-t :t-k]))) ;Only pass through the allowable set of keys + :status)] (= status 410))) :handle-ok ::resource) (defroutes app-routes - (GET "/entity/:id" [id] (entity-endpoint id)) + (GET "/entity/:id" [id] (resource-endpoint "entity" id)) + (GET "/relationship/:id" [id] (resource-endpoint "relationship" id)) (resources "/")) (def handler diff --git a/src/chameleon/route.clj b/src/chameleon/route.clj index 2b30f42..30a2199 100644 --- a/src/chameleon/route.clj +++ b/src/chameleon/route.clj @@ -12,23 +12,22 @@ "Retrieve an entity referenced by id at the provided host. Optionally provide a time 't-k' that defines a query based on when the system knew about the state of the entity." - [host key & [k]] + [host key type & [gallifrey-params]] @(kitclient/request { - :url (str "https://" host "/entity/" key) + :url (str "https://" host "/" type "/" key) :method :get - :query-params (if-let [t-k k] {"t-k" t-k}) + :query-params gallifrey-params :insecure? true :keepalive 300 - :timeout 1000})) + :timeout 20000})) (defn assert-create "Creates an entity in Gallifrey with an initial set of assertions coming from the provided payload" - [host actor key payload] - (print "Final: " payload) + [host actor type key payload & [time-dimensions]] (kitclient/request { - :url (str "https://" host "/entity/" key) + :url (str "https://" host "/" type "/" key) :method :put - :query-params {"actor" actor "create" "true"} + :query-params (into {"actor" actor "create" "true"} time-dimensions) :body payload :insecure? true :keepalive 300 @@ -36,11 +35,11 @@ (defn assert-update "Update an entity in Gallifrey with a set of assertions coming from the provided payload" - [host actor key payload] + [host actor type key payload & [time-dimensions]] (kitclient/request { - :url (str "https://" host "/entity/" key) + :url (str "https://" host "/" type "/" key) :method :put - :query-params {"actor" actor "changes-only" "true"} + :query-params (into {"actor" actor "changes-only" "true"} time-dimensions) :body payload :insecure? true :keepalive 300 @@ -48,24 +47,26 @@ (defn assert-delete "Assert a deletion for an entity in Gallifrey based on the provided key." - [host actor key] + [host actor type key & [time-dimensions]] (kitclient/request { - :url (str "https://" host "/entity/" key) + :url (str "https://" host "/" type "/" key) :method :delete - :query-params {"actor" actor} + :query-params (into {"actor" actor} time-dimensions) :insecure? true :keepalive 300 :timeout 1000})) -(defn assert-gallifrey [host actor payload] +(defn assert-gallifrey [host actor type payload] "Propagates an assertion to Gallifrey based off of an event payload coming in from the event service." (let [{:keys [meta body]} payload - {:keys [key operation]} meta] - (println operation " entity with key " key) + {:keys [key operation time]} meta + time-map (filter val time)] + (println time-map) + (println operation " " type " with key " key) (interpret-response key (case operation "CREATE" - (assert-create host actor key body) + (assert-create host actor type key body time-map) "UPDATE" - (assert-update host actor key body) + (assert-update host actor type key body time-map) "DELETE" - (assert-delete host actor key))))) + (assert-delete host actor type key time-map))))) -- cgit 1.2.3-korg