From 2a0790f65a832ba008e87ae071a2287e0a3bad06 Mon Sep 17 00:00:00 2001 From: Trevor Hartman Date: Thu, 29 Nov 2018 12:39:33 -0700 Subject: [PATCH 1/5] Add initial pagerduty support with teams and users Fix #794 --- project.clj | 2 ++ src/yetibot/commands/pagerduty.clj | 45 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/yetibot/commands/pagerduty.clj diff --git a/project.clj b/project.clj index debe56c0..9fdb438d 100644 --- a/project.clj +++ b/project.clj @@ -26,10 +26,12 @@ :dependencies [[org.clojure/clojure "1.9.0"] [yetibot.core "0.4.54"] + ; apis [twitter-api "1.8.0"] [clj-aws-s3 "0.3.10" :exclusions [joda-time]] [com.google.cloud/google-cloud-storage "1.49.0"] + [pager-duty-api "2.0"] ; scraping [org.jsoup/jsoup "1.11.3"] diff --git a/src/yetibot/commands/pagerduty.clj b/src/yetibot/commands/pagerduty.clj new file mode 100644 index 00000000..3a6baec5 --- /dev/null +++ b/src/yetibot/commands/pagerduty.clj @@ -0,0 +1,45 @@ +(ns yetibot.commands.pagerduty + (:require + [schema.core :as sch] + [clojure.string :as s] + [pager-duty-api.core :refer [with-api-context set-api-context]] + [pager-duty-api.api.schedules :as schedules] + [pager-duty-api.api.teams :as teams] + [pager-duty-api.api.users :as users] + [yetibot.core.config :refer [get-config]] + [taoensso.timbre :refer [info warn error]] + [yetibot.core.hooks :refer [cmd-hook]])) + +(defn config [] (get-config {:token sch/Str} [:pagerduty])) + +(set-api-context + {:auths {"api_key" (str "Token token=" (-> (config) :value :token))}}) + +(defn teams-cmd + "pd teams # list PagerDuty teams + pd teams # list PagerDuty teams matching " + [{match :match}] + (let [query (when (coll? match) (second match)) + {:keys [teams] :as response} (teams/teams-get {:query query})] + (if teams + {:result/data teams + :result/value (map :name teams)} + {:result/error (str "Error fetching teams: " (pr-str response))}))) + +(defn users-cmd + "pd users # list PagerDuty users + pd users # list PagerDuty users matching " + [{match :match}] + (let [query (when (coll? match) (second match)) + {:keys [users] :as response} (users/users-get {:query query})] + (if users + {:result/data users + :result/value (map :name users)} + {:result/error (str "Error fetching users: " (pr-str response))}))) + +(cmd-hook ["pagerduty" #"^pd|pagerduty$"] + #"teams$" teams-cmd + #"teams\s+(\S+)" teams-cmd + #"users$" users-cmd + #"users\s+(\S+)" users-cmd + ) From 0fb90bcddb62735a7c351cf838c04cb8bb8ba79c Mon Sep 17 00:00:00 2001 From: Trevor Hartman Date: Fri, 30 Nov 2018 11:08:26 -0700 Subject: [PATCH 2/5] Add team show and schedules support --- src/yetibot/commands/pagerduty.clj | 70 +++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/yetibot/commands/pagerduty.clj b/src/yetibot/commands/pagerduty.clj index 3a6baec5..424e03c3 100644 --- a/src/yetibot/commands/pagerduty.clj +++ b/src/yetibot/commands/pagerduty.clj @@ -1,5 +1,8 @@ (ns yetibot.commands.pagerduty (:require + [clojure.tools.cli :refer [parse-opts]] + [clj-time.core :as time :refer [days ago]] + [clj-time.format :as time.format] [schema.core :as sch] [clojure.string :as s] [pager-duty-api.core :refer [with-api-context set-api-context]] @@ -13,7 +16,8 @@ (defn config [] (get-config {:token sch/Str} [:pagerduty])) (set-api-context - {:auths {"api_key" (str "Token token=" (-> (config) :value :token))}}) + {:debug false + :auths {"api_key" (str "Token token=" (-> (config) :value :token))}}) (defn teams-cmd "pd teams # list PagerDuty teams @@ -26,6 +30,17 @@ :result/value (map :name teams)} {:result/error (str "Error fetching teams: " (pr-str response))}))) +(defn teams-show-cmd + "pd teams show # list members of a team" + [{[_ team-name] :match}] + (let [{[first-team] :teams} (teams/teams-get {:query team-name}) + _ (info (:id first-team))] + (if first-team + (let [{:keys [users]} (users/users-get {:team-ids [(:id first-team)]})] + {:result/data users + :result/value (map :name users)}) + {:result/error (str "Couldn't find team for `" team-name "`")}))) + (defn users-cmd "pd users # list PagerDuty users pd users # list PagerDuty users matching " @@ -37,9 +52,62 @@ :result/value (map :name users)} {:result/error (str "Error fetching users: " (pr-str response))}))) +(defn schedules-cmd + "pd schedules # list schedules" + [{match :match}] + (let [query (when (coll? match) (second match)) + {:keys [schedules]} (schedules/schedules-get {:query query})] + (if (seq schedules) + {:result/data schedules + :result/value (map :name schedules)} + {:result/error (str "No schedules found" + (when query " for `" query "`"))}))) + +(defn format-date [date-string] + (time.format/unparse + (time.format/formatters :year-month-day) + (time.format/parse date-string))) + +(def schedule-show-opts + [["-s" "--since YYYY-MM-DD" "Since"] + ["-u" "--until YYYY-MM-DD" "Until"]]) + +(defn schedules-show-cmd + "pd schedules show [-s, --since YYYY-MM-DD] [-u, --until YYYY-MM-DD] # show oncall schedule for a given time period + Note: can be a partial match. + + If --since is omitted, it defaults to 7 days ago + If --until is omitted, it defaults to now + " + [{[_ possible-opts-and-query] :match}] + ;; find the schedule + (let [{:keys [options arguments]} (parse-opts + (s/split possible-opts-and-query #"\s") + schedule-show-opts) + query (s/join " " arguments) + {[first-schedule] :schedules} (schedules/schedules-get {:query query})] + (if first-schedule + (let [since (or (:since options) (-> 7 days ago)) + until (or (:until options) (time/now)) + {:keys [schedule]} (schedules/schedules-id-get + (:id first-schedule) + {:until until :since since}) + rendered (-> schedule :final_schedule :rendered_schedule_entries)] + {:result/data schedule + :result/value + (map (fn [{:keys [user start end]}] + (str (format-date start) " - " (format-date end) ": " + (:summary user))) + rendered)}) + {:result/error (str "Could not find a schedule for `" query "`")}))) + (cmd-hook ["pagerduty" #"^pd|pagerduty$"] + #"teams\sshow\s+(\S+)" teams-show-cmd #"teams$" teams-cmd #"teams\s+(\S+)" teams-cmd #"users$" users-cmd #"users\s+(\S+)" users-cmd + #"schedules\sshow\s+(\S.+)$" schedules-show-cmd + #"schedules\s+(\S.+)$" schedules-cmd + #"schedules$" schedules-cmd ) From d3724315e47fb54f196bde5ded58846fce628833 Mon Sep 17 00:00:00 2001 From: Trevor Hartman Date: Fri, 30 Nov 2018 12:52:37 -0700 Subject: [PATCH 3/5] Begin pagerduty tests --- test/yetibot/test/commands/pagerduty.clj | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 test/yetibot/test/commands/pagerduty.clj diff --git a/test/yetibot/test/commands/pagerduty.clj b/test/yetibot/test/commands/pagerduty.clj new file mode 100644 index 00000000..92c758a9 --- /dev/null +++ b/test/yetibot/test/commands/pagerduty.clj @@ -0,0 +1,13 @@ +(ns yetibot.test.commands.pagerduty + (:require + [midje.sweet :refer [namespace-state-changes with-state-changes fact => truthy]] + [yetibot.core.util.command-info :refer [command-execution-info]] + [yetibot.commands.pagerduty :refer :all])) + +(fact + "teams show subcommand matches" + (let [{:keys [match matched-sub-cmd]} (command-execution-info + "pagerduty teams show foo")] + (last match) => "foo" + matched-sub-cmd => #'teams-show-cmd + )) From e454013fce217581e56a6787040f28b0ee7bec35 Mon Sep 17 00:00:00 2001 From: Trevor Hartman Date: Fri, 30 Nov 2018 13:10:34 -0700 Subject: [PATCH 4/5] Add more pagerduty tests --- test/yetibot/test/commands/pagerduty.clj | 37 ++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/test/yetibot/test/commands/pagerduty.clj b/test/yetibot/test/commands/pagerduty.clj index 92c758a9..c247bdea 100644 --- a/test/yetibot/test/commands/pagerduty.clj +++ b/test/yetibot/test/commands/pagerduty.clj @@ -1,13 +1,40 @@ (ns yetibot.test.commands.pagerduty (:require - [midje.sweet :refer [namespace-state-changes with-state-changes fact => truthy]] + [midje.sweet :refer [fact =>]] [yetibot.core.util.command-info :refer [command-execution-info]] [yetibot.commands.pagerduty :refer :all])) (fact "teams show subcommand matches" - (let [{:keys [match matched-sub-cmd]} (command-execution-info - "pagerduty teams show foo")] + (let [{:keys [match matched-sub-cmd]} + (command-execution-info "pagerduty teams show foo")] (last match) => "foo" - matched-sub-cmd => #'teams-show-cmd - )) + matched-sub-cmd => #'teams-show-cmd)) + +(fact + "teams matches the correct command" + (let [{:keys [match matched-sub-cmd]} + (command-execution-info "pagerduty teams foo")] + (first match) => "teams foo" + matched-sub-cmd => #'teams-cmd)) + +(fact + "users matches the correct command" + (let [{:keys [match matched-sub-cmd]} + (command-execution-info "pagerduty users foo")] + (first match) => "users foo" + matched-sub-cmd => #'users-cmd)) + +(fact + "schedules matches the correct command" + (let [{:keys [match matched-sub-cmd]} + (command-execution-info "pagerduty schedules foo")] + (first match) => "schedules foo" + matched-sub-cmd => #'schedules-cmd)) + +(fact + "schedules show matches the correct command" + (let [{:keys [match matched-sub-cmd]} + (command-execution-info "pagerduty schedules show foo")] + (first match) => "schedules show foo" + matched-sub-cmd => #'schedules-show-cmd)) From 9b5036da59ba22ac9f63c86a7b27a9b19eefcd0e Mon Sep 17 00:00:00 2001 From: Trevor Hartman Date: Fri, 30 Nov 2018 13:15:43 -0700 Subject: [PATCH 5/5] Upgrade cloverage --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index 9fdb438d..f50ce039 100644 --- a/project.clj +++ b/project.clj @@ -64,7 +64,7 @@ :plugins [[lein-exec "0.3.5"] [lein-environ "1.0.3"] - [lein-cloverage "1.0.7-SNAPSHOT"] + [lein-cloverage "1.0.13"] [lein-ring "0.9.5"] [io.sarnowski/lein-docker "1.1.0"]]