diff options
Diffstat (limited to 'modules/role/manifests/cryptoportfolio.pp')
-rw-r--r-- | modules/role/manifests/cryptoportfolio.pp | 438 |
1 files changed, 24 insertions, 414 deletions
diff --git a/modules/role/manifests/cryptoportfolio.pp b/modules/role/manifests/cryptoportfolio.pp index bec247e..799e297 100644 --- a/modules/role/manifests/cryptoportfolio.pp +++ b/modules/role/manifests/cryptoportfolio.pp | |||
@@ -1,9 +1,22 @@ | |||
1 | class role::cryptoportfolio { | 1 | class role::cryptoportfolio ( |
2 | ensure_resource('exec', 'systemctl daemon-reload', { | 2 | String $user, |
3 | command => '/usr/bin/systemctl daemon-reload', | 3 | String $group, |
4 | refreshonly => true | 4 | String $home, |
5 | }) | 5 | Optional[String] $env = "prod", |
6 | 6 | Optional[String] $webhook_url = undef, | |
7 | String $pg_user, | ||
8 | String $pg_user_replication, | ||
9 | String $pg_db, | ||
10 | Optional[String] $pg_hostname = "localhost", | ||
11 | Optional[String] $pg_port = "5432", | ||
12 | Optional[String] $web_host = undef, | ||
13 | Optional[String] $web_port = "", | ||
14 | Optional[Boolean] $web_ssl = true, | ||
15 | Optional[String] $front_version = undef, | ||
16 | Optional[String] $front_sha256 = undef, | ||
17 | Optional[String] $bot_version = undef, | ||
18 | Optional[String] $bot_sha256 = undef, | ||
19 | ) { | ||
7 | include "base_installation" | 20 | include "base_installation" |
8 | 21 | ||
9 | include "profile::tools" | 22 | include "profile::tools" |
@@ -11,420 +24,17 @@ class role::cryptoportfolio { | |||
11 | include "profile::apache" | 24 | include "profile::apache" |
12 | include "profile::xmr_stak" | 25 | include "profile::xmr_stak" |
13 | 26 | ||
14 | $password_seed = lookup("base_installation::puppet_pass_seed") |$key| { {} } | 27 | contain "role::cryptoportfolio::postgresql" |
15 | 28 | contain "role::cryptoportfolio::apache" | |
16 | $cf_pg_user = "cryptoportfolio" | ||
17 | $cf_pg_user_replication = "cryptoportfolio_replication" | ||
18 | $cf_pg_db = "cryptoportfolio" | ||
19 | $cf_pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio") | ||
20 | $cf_pg_replication_password = generate_password(24, $password_seed, "postgres_cryptoportfolio_replication") | ||
21 | $cf_pg_hostname = "localhost" | ||
22 | $cf_pg_port = "5432" | ||
23 | $cf_pg_host = "${cf_pg_hostname}:${cf_pg_port}" | ||
24 | |||
25 | $cf_user = "cryptoportfolio" | ||
26 | $cf_group = "cryptoportfolio" | ||
27 | $cf_home = "/opt/cryptoportfolio" | ||
28 | $cf_env = "prod" | ||
29 | $cf_front_app_host = lookup("base_installation::system_hostname") |$key| { "example.com" } | ||
30 | $cf_front_app_port = "" | ||
31 | $cf_front_app_ssl = "true" | ||
32 | $cf_front_app = "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front" | ||
33 | $cf_front_app_api_workdir = "${cf_front_app}/cmd/app" | ||
34 | $cf_front_app_api_bin = "${cf_front_app_api_workdir}/cryptoportfolio-app" | ||
35 | $cf_front_app_api_conf = "${cf_home}/conf.toml" | ||
36 | $cf_front_app_api_secret = generate_password(24, $password_seed, "cryptoportfolio_api_secret") | ||
37 | |||
38 | $cf_front_app_static_conf = "${cf_front_app}/cmd/web/env/prod.env" | ||
39 | |||
40 | $cf_bot_app = "${cf_home}/bot" | ||
41 | $cf_bot_app_conf = "${cf_home}/bot_config.ini" | ||
42 | $cf_bot_app_reports = "${cf_home}/bot_reports" | ||
43 | |||
44 | $cf_webhook_url = lookup("cryptoportfolio::slack_webhook") |$key| { "" } | ||
45 | |||
46 | file { "/var/lib/postgres/data/certs": | ||
47 | ensure => directory, | ||
48 | mode => "0700", | ||
49 | owner => $::profile::postgresql::pg_user, | ||
50 | group => $::profile::postgresql::pg_user, | ||
51 | require => File["/var/lib/postgres"], | ||
52 | } | ||
53 | 29 | ||
54 | file { "/var/lib/postgres/data/certs/cert.pem": | 30 | contain "role::cryptoportfolio::notify" |
55 | source => "file:///etc/letsencrypt/live/$cf_front_app_host/cert.pem", | ||
56 | mode => "0600", | ||
57 | links => "follow", | ||
58 | owner => $::profile::postgresql::pg_user, | ||
59 | group => $::profile::postgresql::pg_user, | ||
60 | require => [Letsencrypt::Certonly[$cf_front_app_host], File["/var/lib/postgres/data/certs"]] | ||
61 | } | ||
62 | |||
63 | file { "/var/lib/postgres/data/certs/privkey.pem": | ||
64 | source => "file:///etc/letsencrypt/live/$cf_front_app_host/privkey.pem", | ||
65 | mode => "0600", | ||
66 | links => "follow", | ||
67 | owner => $::profile::postgresql::pg_user, | ||
68 | group => $::profile::postgresql::pg_user, | ||
69 | require => [Letsencrypt::Certonly[$cf_front_app_host], File["/var/lib/postgres/data/certs"]] | ||
70 | } | ||
71 | |||
72 | postgresql::server::config_entry { "wal_level": | ||
73 | value => "logical", | ||
74 | } | ||
75 | |||
76 | postgresql::server::config_entry { "ssl": | ||
77 | value => "on", | ||
78 | require => Letsencrypt::Certonly[$cf_front_app_host], | ||
79 | } | ||
80 | |||
81 | postgresql::server::config_entry { "ssl_cert_file": | ||
82 | value => "/var/lib/postgres/data/certs/cert.pem", | ||
83 | require => Letsencrypt::Certonly[$cf_front_app_host], | ||
84 | } | ||
85 | |||
86 | postgresql::server::config_entry { "ssl_key_file": | ||
87 | value => "/var/lib/postgres/data/certs/privkey.pem", | ||
88 | require => Letsencrypt::Certonly[$cf_front_app_host], | ||
89 | } | ||
90 | |||
91 | postgresql::server::db { $cf_pg_db: | ||
92 | user => $cf_pg_user, | ||
93 | password => postgresql_password($cf_pg_user, $cf_pg_password), | ||
94 | } | ||
95 | -> | ||
96 | postgresql_psql { "CREATE PUBLICATION ${cf_pg_db}_publication FOR ALL TABLES": | ||
97 | db => $cf_pg_db, | ||
98 | unless => "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '${cf_pg_db}_publication'", | ||
99 | } | ||
100 | -> | ||
101 | postgresql::server::role { $cf_pg_user_replication: | ||
102 | db => $cf_pg_db, | ||
103 | replication => true, | ||
104 | password_hash => postgresql_password($cf_pg_user_replication, $cf_pg_replication_password), | ||
105 | } | ||
106 | -> | ||
107 | postgresql::server::database_grant { $cf_pg_user_replication: | ||
108 | db => $cf_pg_db, | ||
109 | privilege => "CONNECT", | ||
110 | role => $cf_pg_user_replication, | ||
111 | } | ||
112 | -> | ||
113 | postgresql::server::grant { "all tables in schema:public:$cf_pg_user_replication": | ||
114 | db => $cf_pg_db, | ||
115 | role => $cf_pg_user_replication, | ||
116 | privilege => "SELECT", | ||
117 | object_type => "ALL TABLES IN SCHEMA", | ||
118 | object_name => "public", | ||
119 | } | ||
120 | -> | ||
121 | postgresql::server::grant { "all sequences in schema:public:$cf_pg_user_replication": | ||
122 | db => $cf_pg_db, | ||
123 | role => $cf_pg_user_replication, | ||
124 | privilege => "SELECT", | ||
125 | object_type => "ALL SEQUENCES IN SCHEMA", | ||
126 | object_name => "public", | ||
127 | } | ||
128 | |||
129 | postgresql::server::pg_hba_rule { 'allow localhost TCP access to cryptoportfolio user': | ||
130 | type => 'host', | ||
131 | database => $cf_pg_db, | ||
132 | user => $cf_pg_user, | ||
133 | address => '127.0.0.1/32', | ||
134 | auth_method => 'md5', | ||
135 | order => "b0", | ||
136 | } | ||
137 | postgresql::server::pg_hba_rule { 'allow localhost ip6 TCP access to cryptoportfolio user': | ||
138 | type => 'host', | ||
139 | database => $cf_pg_db, | ||
140 | user => $cf_pg_user, | ||
141 | address => '::1/128', | ||
142 | auth_method => 'md5', | ||
143 | order => "b0", | ||
144 | } | ||
145 | |||
146 | postgresql::server::pg_hba_rule { 'allow TCP access to replication user from immae.eu': | ||
147 | type => 'hostssl', | ||
148 | database => $cf_pg_db, | ||
149 | user => $cf_pg_user_replication, | ||
150 | address => 'immae.eu', | ||
151 | auth_method => 'md5', | ||
152 | order => "b0", | ||
153 | } | ||
154 | |||
155 | letsencrypt::certonly { $cf_front_app_host: ; | ||
156 | default: * => $::profile::apache::letsencrypt_certonly_default; | ||
157 | } | ||
158 | |||
159 | class { 'apache::mod::headers': } | ||
160 | apache::vhost { $cf_front_app_host: | ||
161 | port => '443', | ||
162 | docroot => false, | ||
163 | manage_docroot => false, | ||
164 | proxy_dest => "http://localhost:8000", | ||
165 | request_headers => 'set X-Forwarded-Proto "https"', | ||
166 | ssl => true, | ||
167 | ssl_cert => "/etc/letsencrypt/live/$cf_front_app_host/cert.pem", | ||
168 | ssl_key => "/etc/letsencrypt/live/$cf_front_app_host/privkey.pem", | ||
169 | ssl_chain => "/etc/letsencrypt/live/$cf_front_app_host/chain.pem", | ||
170 | require => Letsencrypt::Certonly[$cf_front_app_host], | ||
171 | proxy_preserve_host => true; | ||
172 | default: * => $::profile::apache::apache_vhost_default; | ||
173 | } | ||
174 | |||
175 | user { $cf_user: | ||
176 | name => $cf_user, | ||
177 | ensure => "present", | ||
178 | managehome => true, | ||
179 | home => $cf_home, | ||
180 | system => true, | ||
181 | password => '!!', | ||
182 | } | ||
183 | |||
184 | file { "/usr/local/bin/slack-notify": | ||
185 | mode => "0755", | ||
186 | source => "puppet:///modules/role/cryptoportfolio/slack-notify.py", | ||
187 | } | ||
188 | |||
189 | $front_version = lookup("cryptoportfolio::front_version") |$key| { {} } | ||
190 | $front_sha256 = lookup("cryptoportfolio::front_sha256") |$key| { {} } | ||
191 | |||
192 | $bot_version = lookup("cryptoportfolio::bot_version") |$key| { {} } | ||
193 | $bot_sha256 = lookup("cryptoportfolio::bot_sha256") |$key| { {} } | ||
194 | 31 | ||
195 | unless empty($bot_version) { | 32 | unless empty($bot_version) { |
196 | ensure_packages(["python", "python-pip"]) | 33 | contain "role::cryptoportfolio::bot" |
197 | |||
198 | file { $cf_bot_app: | ||
199 | ensure => "directory", | ||
200 | mode => "0700", | ||
201 | owner => $cf_user, | ||
202 | group => $cf_group, | ||
203 | require => User[$cf_user], | ||
204 | } | ||
205 | |||
206 | archive { "${cf_home}/trader_${bot_version}.tar.gz": | ||
207 | path => "${cf_home}/trader_${bot_version}.tar.gz", | ||
208 | source => "https://git.immae.eu/releases/cryptoportfolio/trader/trader_${bot_version}.tar.gz", | ||
209 | checksum_type => "sha256", | ||
210 | checksum => $bot_sha256, | ||
211 | cleanup => false, | ||
212 | extract => true, | ||
213 | user => $cf_user, | ||
214 | username => $facts["ec2_metadata"]["hostname"], | ||
215 | password => generate_password(24, $password_seed, "ldap"), | ||
216 | extract_path => $cf_bot_app, | ||
217 | require => [User[$cf_user], File[$cf_bot_app]], | ||
218 | } ~> | ||
219 | exec { "py-cryptoportfolio-dependencies": | ||
220 | cwd => $cf_bot_app, | ||
221 | user => $cf_user, | ||
222 | environment => ["HOME=${cf_home}"], | ||
223 | command => "/usr/bin/make install", | ||
224 | require => User[$cf_user], | ||
225 | refreshonly => true, | ||
226 | before => [ | ||
227 | File[$cf_bot_app_conf], | ||
228 | Cron["py-cryptoportfolio-before"], | ||
229 | Cron["py-cryptoportfolio-after"], | ||
230 | ] | ||
231 | } | ||
232 | |||
233 | file { $cf_bot_app_conf: | ||
234 | owner => $cf_user, | ||
235 | group => $cf_group, | ||
236 | mode => "0600", | ||
237 | content => template("role/cryptoportfolio/bot_config.ini.erb"), | ||
238 | require => [ | ||
239 | User[$cf_user], | ||
240 | Archive["${cf_home}/trader_${bot_version}.tar.gz"], | ||
241 | ], | ||
242 | } | ||
243 | |||
244 | cron { "py-cryptoportfolio-before": | ||
245 | ensure => present, | ||
246 | command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --before", | ||
247 | user => "cryptoportfolio", | ||
248 | weekday => 7, # Sunday | ||
249 | hour => 22, | ||
250 | minute => 30, | ||
251 | environment => ["HOME=${cf_home}","PATH=/usr/bin/"], | ||
252 | require => [ | ||
253 | File[$cf_bot_app_conf], | ||
254 | Archive["${cf_home}/trader_${bot_version}.tar.gz"] | ||
255 | ], | ||
256 | } | ||
257 | |||
258 | cron { "py-cryptoportfolio-after": | ||
259 | ensure => present, | ||
260 | command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --after", | ||
261 | user => "cryptoportfolio", | ||
262 | weekday => 1, # Monday | ||
263 | hour => 1, | ||
264 | minute => 0, | ||
265 | environment => ["HOME=${cf_home}","PATH=/usr/bin/"], | ||
266 | require => [ | ||
267 | File[$cf_bot_app_conf], | ||
268 | Archive["${cf_home}/trader_${bot_version}.tar.gz"] | ||
269 | ], | ||
270 | } | ||
271 | |||
272 | unless empty($cf_webhook_url) { | ||
273 | exec { "bot-slack-notify": | ||
274 | refreshonly => true, | ||
275 | environment => [ | ||
276 | "P_PROJECT=Trader", | ||
277 | "P_WEBHOOK=${cf_webhook_url}", | ||
278 | "P_VERSION=${bot_version}", | ||
279 | "P_HOST=${cf_front_app_host}", | ||
280 | "P_HTTPS=${cf_front_app_ssl}", | ||
281 | ], | ||
282 | command => "/usr/local/bin/slack-notify", | ||
283 | require => File["/usr/local/bin/slack-notify"], | ||
284 | subscribe => Exec["py-cryptoportfolio-dependencies"], | ||
285 | } | ||
286 | } | ||
287 | } | 34 | } |
288 | 35 | ||
289 | # FIXME: restore backup | 36 | # FIXME: restore backup |
290 | unless empty($front_version) { | 37 | unless empty($front_version) { |
291 | ensure_packages(["go", "npm", "nodejs", "yarn"]) | 38 | contain "role::cryptoportfolio::front" |
292 | |||
293 | file { [ | ||
294 | "${cf_home}/go/", | ||
295 | "${cf_home}/go/src", | ||
296 | "${cf_home}/go/src/immae.eu", | ||
297 | "${cf_home}/go/src/immae.eu/Immae", | ||
298 | "${cf_home}/go/src/immae.eu/Immae/Projets", | ||
299 | "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies", | ||
300 | "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio", | ||
301 | $cf_front_app]: | ||
302 | ensure => "directory", | ||
303 | mode => "0700", | ||
304 | owner => $cf_user, | ||
305 | group => $cf_group, | ||
306 | require => User[$cf_user], | ||
307 | } | ||
308 | |||
309 | file { "${cf_home}/front": | ||
310 | ensure => "link", | ||
311 | target => $cf_front_app, | ||
312 | before => File[$cf_front_app], | ||
313 | } | ||
314 | |||
315 | file { "/etc/systemd/system/cryptoportfolio-app.service": | ||
316 | mode => "0644", | ||
317 | owner => "root", | ||
318 | group => "root", | ||
319 | content => template("role/cryptoportfolio/cryptoportfolio-app.service.erb"), | ||
320 | notify => Exec["systemctl daemon-reload"], | ||
321 | } | ||
322 | |||
323 | service { 'cryptoportfolio-app': | ||
324 | enable => true, | ||
325 | ensure => "running", | ||
326 | subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]], | ||
327 | require => [ | ||
328 | File["/etc/systemd/system/cryptoportfolio-app.service"], | ||
329 | Postgresql::Server::Db[$cf_pg_db] | ||
330 | ], | ||
331 | } ~> | ||
332 | exec { "dump $cf_pg_db structure": | ||
333 | refreshonly => true, | ||
334 | user => $::profile::postgresql::pg_user, | ||
335 | group => $::profile::postgresql::pg_user, | ||
336 | command => "/usr/bin/pg_dump --schema-only --clean --no-publications $cf_pg_db > /var/lib/postgres/${cf_pg_db}.schema", | ||
337 | } | ||
338 | |||
339 | archive { "${cf_home}/front_${front_version}.tar.gz": | ||
340 | path => "${cf_home}/front_${front_version}.tar.gz", | ||
341 | source => "https://git.immae.eu/releases/cryptoportfolio/front/front_${front_version}.tar.gz", | ||
342 | checksum_type => "sha256", | ||
343 | checksum => $front_sha256, | ||
344 | cleanup => false, | ||
345 | extract => true, | ||
346 | user => $cf_user, | ||
347 | username => $facts["ec2_metadata"]["hostname"], | ||
348 | password => generate_password(24, $password_seed, "ldap"), | ||
349 | extract_path => $cf_front_app, | ||
350 | require => [User[$cf_user], File[$cf_front_app]], | ||
351 | notify => [ | ||
352 | Exec["web-cryptoportfolio-dependencies"], | ||
353 | Exec["go-get-dep"], | ||
354 | ] | ||
355 | } | ||
356 | |||
357 | # Api | ||
358 | file { $cf_front_app_api_conf: | ||
359 | owner => $cf_user, | ||
360 | group => $cf_group, | ||
361 | mode => "0600", | ||
362 | content => template("role/cryptoportfolio/api_conf.toml.erb"), | ||
363 | before => Exec["go-cryptoportfolio-app"], | ||
364 | } | ||
365 | |||
366 | exec { "go-get-dep": | ||
367 | user => $cf_user, | ||
368 | environment => ["HOME=${cf_home}"], | ||
369 | creates => "${cf_home}/go/bin/dep", | ||
370 | command => "/usr/bin/go get -u github.com/golang/dep/cmd/dep", | ||
371 | refreshonly => true, | ||
372 | } ~> | ||
373 | exec { "go-cryptoportfolio-dependencies": | ||
374 | cwd => $cf_front_app, | ||
375 | user => $cf_user, | ||
376 | environment => ["HOME=${cf_home}"], | ||
377 | command => "${cf_home}/go/bin/dep ensure", | ||
378 | refreshonly => true, | ||
379 | } ~> | ||
380 | exec { "go-cryptoportfolio-app": | ||
381 | cwd => $cf_front_app_api_workdir, | ||
382 | user => $cf_user, | ||
383 | environment => ["HOME=${cf_home}"], | ||
384 | command => "/usr/bin/make build", | ||
385 | refreshonly => true, | ||
386 | } | ||
387 | |||
388 | # Static pages | ||
389 | file { $cf_front_app_static_conf: | ||
390 | owner => $cf_user, | ||
391 | group => $cf_group, | ||
392 | mode => "0600", | ||
393 | content => template("role/cryptoportfolio/static_conf.env.erb"), | ||
394 | before => Exec["web-cryptoportfolio-build"], | ||
395 | } | ||
396 | |||
397 | exec { "web-cryptoportfolio-dependencies": | ||
398 | cwd => "${cf_front_app}/cmd/web", | ||
399 | user => $cf_user, | ||
400 | environment => ["HOME=${cf_home}"], | ||
401 | command => "/usr/bin/make install", | ||
402 | refreshonly => true, | ||
403 | require => [Package["npm"], Package["nodejs"], Package["yarn"]] | ||
404 | } ~> | ||
405 | exec { "web-cryptoportfolio-build": | ||
406 | cwd => "${cf_front_app}/cmd/web", | ||
407 | user => $cf_user, | ||
408 | environment => ["HOME=${cf_home}"], | ||
409 | path => ["${cf_front_app}/cmd/web/node_modules/.bin/", "/usr/bin"], | ||
410 | command => "/usr/bin/make static ENV=${cf_env}", | ||
411 | refreshonly => true, | ||
412 | } | ||
413 | |||
414 | unless empty($cf_webhook_url) { | ||
415 | exec { "front-slack-notify": | ||
416 | refreshonly => true, | ||
417 | environment => [ | ||
418 | "P_PROJECT=Front", | ||
419 | "P_WEBHOOK=${cf_webhook_url}", | ||
420 | "P_VERSION=${front_version}", | ||
421 | "P_HOST=${cf_front_app_host}", | ||
422 | "P_HTTPS=${cf_front_app_ssl}", | ||
423 | ], | ||
424 | command => "/usr/local/bin/slack-notify", | ||
425 | require => File["/usr/local/bin/slack-notify"], | ||
426 | subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]], | ||
427 | } | ||
428 | } | ||
429 | } | 39 | } |
430 | } | 40 | } |