-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.clj
132 lines (113 loc) · 4.62 KB
/
core.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
(ns io.schemamap.core
(:gen-class)
(:require [clojure.tools.logging :as log]
[next.jdbc :as jdbc])
(:import
(org.flywaydb.core Flyway)
(javax.sql DataSource)))
(defn run-migrations! [datasource]
(.. (Flyway/configure)
(defaultSchema "schemamap")
(locations (into-array String ["classpath:io/schemamap/db/migrations"]))
(createSchemas true)
(dataSource datasource)
(load)
(migrate)))
(defn start-ssh-forwarding!
[agent {:keys [host username local-port remote-port
connect-timeout]
:or {connect-timeout 5000}}]
(let [ssh-service-port 22 #_2222
session ((requiring-resolve 'clj-ssh.ssh/session)
agent host {:port ssh-service-port
:username username
:strict-host-key-checking :no})]
(log/infof "Trying connecting to %s@%s:%s" username host ssh-service-port)
((requiring-resolve 'clj-ssh.ssh/connect) session connect-timeout)
(log/infof "Connected to %s@%s:%s" username host ssh-service-port)
(log/infof "Forwarding local port %s to remote port %s" local-port remote-port)
((requiring-resolve 'clj-ssh.ssh/forward-remote-port) session remote-port local-port)
session))
(defn read-i18n-string!
^String [input]
(cond
(string? input)
input
(instance? java.io.File input)
(slurp input)
;; explicitly not implementing Clojure map -> JSON string
;; as that would require a runtime dependency on a particular JSON library
:else
(throw (ex-info "Unsupported i18n input provided, please provide a java.io.File or a JSON string"
{:input input
:class (class input)}))))
(defn valid-pg-role-name? [role-name]
(boolean
(some->> role-name
(re-matches #"^[a-zA-Z_][a-zA-Z0-9_]*$"))))
(defn alter-schemamap-schema!
[{:keys [^DataSource datasource application-db-roles i18n]}]
(with-open [conn (jdbc/get-connection datasource)]
(doseq [role application-db-roles]
(when-not (valid-pg-role-name? role)
(throw (ex-info "Invalid role name provided" {:role-name role})))
(log/info "Granting schemamap schema usage permissions to role:" application-db-roles)
(jdbc/execute! conn [(format "grant usage on schema schemamap to %s" role)])
(jdbc/execute! conn [(format "grant execute on all functions in schema schemamap to %s" role)])
(jdbc/execute! conn [(format "grant select on schemamap.i18n_stored, schemamap.schema_metadata_overview to %s" role)]))
(when i18n
(log/info "Overriding schemamap.i18n() value")
(jdbc/execute! conn ["select schemamap.update_i18n(?::jsonb)" (read-i18n-string! i18n)]))))
(defn maybe-ssh-port-forward-postgres!
[{:keys [port-forward-host
port-forward-remote-port
port-forward-port
port-forward-user
port-forward-postgres?]
:or {port-forward-postgres? false
port-forward-host "pgtunnel.eu.schemamap.io"}}]
(if (and port-forward-remote-port port-forward-postgres?)
(do
(log/info "Starting Postgres SSH port forwarding to" port-forward-host)
(let [ssh-agent ((requiring-resolve 'clj-ssh.ssh/ssh-agent) {:use-system-ssh-agent true})
local-port port-forward-port]
(start-ssh-forwarding!
ssh-agent
{:host port-forward-host
:username port-forward-user
:local-port local-port
:remote-port port-forward-remote-port})))
(log/debug "Skipping Postgres SSH port forwarding")))
(defn init!
[{:keys [^DataSource datasource
i18n
port-forward-host
port-forward-remote-port
port-forward-port
port-forward-user
port-forward-postgres?
application-db-roles]
:as params}]
(log/info "Migrating schemamap schema")
(run-migrations! datasource)
(log/info "Migrated schemamap schema")
(alter-schemamap-schema! params)
{:session (maybe-ssh-port-forward-postgres! params)})
;; TODO: implement java.io.Closeable to allow `with-open` macro usage
(defn close! [{:keys [session]}]
(when session
(.disconnect session)))
(comment
(do
(require '[clj-ssh.ssh :as ssh])
(def ssh-agent (ssh/ssh-agent {:use-system-ssh-agent true}))
(.getIdentityNames ssh-agent))
(def session
(start-ssh-forwarding!
ssh-agent
{:host "pgtunnel.eu.schemamap.io"
:username "pgtunnel_frutico_krisz"
:local-port 5437
:remote-port 11111
:connect-timeout 2000}))
(.disconnect session))