1use crate::aws::{
4 s3::{DEPLOYMENTS_PREFIX, TOOLS_BINARIES_PREFIX, TOOLS_CONFIGS_PREFIX, WGET},
5 Architecture,
6};
7
8const DEPLOYER_VERSION: &str = env!("CARGO_PKG_VERSION");
10
11pub const PROMETHEUS_VERSION: &str = "3.2.0";
13
14pub const PROMTAIL_VERSION: &str = "3.4.2";
16
17pub const NODE_EXPORTER_VERSION: &str = "1.9.0";
19
20pub const LOKI_VERSION: &str = "3.4.2";
22
23pub const TEMPO_VERSION: &str = "2.7.1";
25
26pub const PYROSCOPE_VERSION: &str = "1.12.0";
28
29pub const GRAFANA_VERSION: &str = "11.5.2";
31
32pub const SAMPLY_VERSION: &str = "0.13.1";
34
35pub const LIBJEMALLOC2_VERSION: &str = "5.3.0-2build1";
37
38pub const LOGROTATE_VERSION: &str = "3.21.0-2build1";
40
41pub const LIBFONTCONFIG1_VERSION: &str = "2.15.0-1.1ubuntu2";
43
44pub const FONTCONFIG_CONFIG_VERSION: &str = "2.15.0-1.1ubuntu2";
46
47pub const UNZIP_VERSION: &str = "6.0-28ubuntu4";
49
50pub const ADDUSER_VERSION: &str = "3.137ubuntu1";
52
53pub const FONTS_DEJAVU_MONO_VERSION: &str = "2.37-8";
55
56pub const FONTS_DEJAVU_CORE_VERSION: &str = "2.37-8";
58
59pub const MUSL_VERSION: &str = "1.2.4-2";
61
62const UBUNTU_ARCHIVE_ARM64: &str = "http://ports.ubuntu.com/ubuntu-ports/pool";
64
65const UBUNTU_ARCHIVE_X86_64: &str = "http://archive.ubuntu.com/ubuntu/pool";
67
68pub(crate) fn prometheus_bin_s3_key(version: &str, architecture: Architecture) -> String {
79 format!(
80 "{TOOLS_BINARIES_PREFIX}/prometheus/{version}/linux-{arch}/prometheus-{version}.linux-{arch}.tar.gz",
81 arch = architecture.as_str()
82 )
83}
84
85pub(crate) fn grafana_bin_s3_key(version: &str, architecture: Architecture) -> String {
86 format!(
87 "{TOOLS_BINARIES_PREFIX}/grafana/{version}/linux-{arch}/grafana_{version}_{arch}.deb",
88 arch = architecture.as_str()
89 )
90}
91
92pub(crate) fn loki_bin_s3_key(version: &str, architecture: Architecture) -> String {
93 format!(
94 "{TOOLS_BINARIES_PREFIX}/loki/{version}/linux-{arch}/loki-linux-{arch}.zip",
95 arch = architecture.as_str()
96 )
97}
98
99pub(crate) fn pyroscope_bin_s3_key(version: &str, architecture: Architecture) -> String {
100 format!(
101 "{TOOLS_BINARIES_PREFIX}/pyroscope/{version}/linux-{arch}/pyroscope_{version}_linux_{arch}.tar.gz",
102 arch = architecture.as_str()
103 )
104}
105
106pub(crate) fn tempo_bin_s3_key(version: &str, architecture: Architecture) -> String {
107 format!(
108 "{TOOLS_BINARIES_PREFIX}/tempo/{version}/linux-{arch}/tempo_{version}_linux_{arch}.tar.gz",
109 arch = architecture.as_str()
110 )
111}
112
113pub(crate) fn node_exporter_bin_s3_key(version: &str, architecture: Architecture) -> String {
114 format!(
115 "{TOOLS_BINARIES_PREFIX}/node-exporter/{version}/linux-{arch}/node_exporter-{version}.linux-{arch}.tar.gz",
116 arch = architecture.as_str()
117 )
118}
119
120pub(crate) fn promtail_bin_s3_key(version: &str, architecture: Architecture) -> String {
121 format!(
122 "{TOOLS_BINARIES_PREFIX}/promtail/{version}/linux-{arch}/promtail-linux-{arch}.zip",
123 arch = architecture.as_str()
124 )
125}
126
127pub(crate) fn samply_bin_s3_key(version: &str, architecture: Architecture) -> String {
128 let arch = match architecture {
129 Architecture::Arm64 => "aarch64",
130 Architecture::X86_64 => "x86_64",
131 };
132 format!("{TOOLS_BINARIES_PREFIX}/samply/{version}/linux-{arch}/samply-{arch}-unknown-linux-gnu.tar.xz")
133}
134
135pub(crate) fn libjemalloc_bin_s3_key(version: &str, architecture: Architecture) -> String {
136 format!(
137 "{TOOLS_BINARIES_PREFIX}/libjemalloc2/{version}/linux-{arch}/libjemalloc2_{version}_{arch}.deb",
138 arch = architecture.as_str()
139 )
140}
141
142pub(crate) fn logrotate_bin_s3_key(version: &str, architecture: Architecture) -> String {
143 format!(
144 "{TOOLS_BINARIES_PREFIX}/logrotate/{version}/linux-{arch}/logrotate_{version}_{arch}.deb",
145 arch = architecture.as_str()
146 )
147}
148
149pub(crate) fn libfontconfig_bin_s3_key(version: &str, architecture: Architecture) -> String {
150 format!(
151 "{TOOLS_BINARIES_PREFIX}/libfontconfig1/{version}/linux-{arch}/libfontconfig1_{version}_{arch}.deb",
152 arch = architecture.as_str()
153 )
154}
155
156pub(crate) fn fontconfig_config_bin_s3_key(version: &str, architecture: Architecture) -> String {
158 format!(
159 "{TOOLS_BINARIES_PREFIX}/fontconfig-config/{version}/linux-{arch}/fontconfig-config_{version}_{arch}.deb",
160 arch = architecture.as_str()
161 )
162}
163
164pub(crate) fn unzip_bin_s3_key(version: &str, architecture: Architecture) -> String {
165 format!(
166 "{TOOLS_BINARIES_PREFIX}/unzip/{version}/linux-{arch}/unzip_{version}_{arch}.deb",
167 arch = architecture.as_str()
168 )
169}
170
171pub(crate) fn adduser_bin_s3_key(version: &str) -> String {
173 format!("{TOOLS_BINARIES_PREFIX}/adduser/{version}/adduser_{version}_all.deb")
174}
175
176pub(crate) fn fonts_dejavu_mono_bin_s3_key(version: &str) -> String {
178 format!(
179 "{TOOLS_BINARIES_PREFIX}/fonts-dejavu-mono/{version}/fonts-dejavu-mono_{version}_all.deb"
180 )
181}
182
183pub(crate) fn fonts_dejavu_core_bin_s3_key(version: &str) -> String {
185 format!(
186 "{TOOLS_BINARIES_PREFIX}/fonts-dejavu-core/{version}/fonts-dejavu-core_{version}_all.deb"
187 )
188}
189
190pub(crate) fn musl_bin_s3_key(version: &str, architecture: Architecture) -> String {
192 format!(
193 "{TOOLS_BINARIES_PREFIX}/musl/{version}/linux-{arch}/musl_{version}_{arch}.deb",
194 arch = architecture.as_str()
195 )
196}
197
198pub fn prometheus_service_s3_key() -> String {
203 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/prometheus/service")
204}
205
206pub fn grafana_datasources_s3_key() -> String {
207 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/grafana/datasources.yml")
208}
209
210pub fn grafana_dashboards_s3_key() -> String {
211 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/grafana/all.yml")
212}
213
214pub fn loki_config_s3_key() -> String {
215 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/loki/config.yml")
216}
217
218pub fn loki_service_s3_key() -> String {
219 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/loki/service")
220}
221
222pub fn pyroscope_config_s3_key() -> String {
223 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/pyroscope/config.yml")
224}
225
226pub fn pyroscope_service_s3_key() -> String {
227 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/pyroscope/service")
228}
229
230pub fn tempo_config_s3_key() -> String {
231 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/tempo/config.yml")
232}
233
234pub fn tempo_service_s3_key() -> String {
235 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/tempo/service")
236}
237
238pub fn node_exporter_service_s3_key() -> String {
239 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/node-exporter/service")
240}
241
242pub fn promtail_service_s3_key() -> String {
243 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/promtail/service")
244}
245
246pub fn pyroscope_agent_service_s3_key() -> String {
249 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/pyroscope/agent.service")
250}
251
252pub fn pyroscope_agent_timer_s3_key() -> String {
253 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/pyroscope/agent.timer")
254}
255
256pub fn logrotate_config_s3_key() -> String {
259 format!("{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/system/logrotate.conf")
260}
261
262pub(crate) fn binary_service_s3_key_for_arch(architecture: Architecture) -> String {
265 format!(
266 "{TOOLS_CONFIGS_PREFIX}/{DEPLOYER_VERSION}/binary/service-{arch}",
267 arch = architecture.as_str()
268 )
269}
270
271pub fn binary_s3_key(tag: &str, digest: &str) -> String {
273 format!("{DEPLOYMENTS_PREFIX}/{tag}/binaries/{digest}")
274}
275
276pub fn config_s3_key(tag: &str, digest: &str) -> String {
278 format!("{DEPLOYMENTS_PREFIX}/{tag}/configs/{digest}")
279}
280
281pub fn hosts_s3_key(tag: &str, digest: &str) -> String {
283 format!("{DEPLOYMENTS_PREFIX}/{tag}/hosts/{digest}")
284}
285
286pub fn promtail_s3_key(tag: &str, digest: &str) -> String {
288 format!("{DEPLOYMENTS_PREFIX}/{tag}/promtail/{digest}")
289}
290
291pub fn pyroscope_s3_key(tag: &str, digest: &str) -> String {
293 format!("{DEPLOYMENTS_PREFIX}/{tag}/pyroscope/{digest}")
294}
295
296pub fn monitoring_s3_key(tag: &str, digest: &str) -> String {
298 format!("{DEPLOYMENTS_PREFIX}/{tag}/monitoring/{digest}")
299}
300
301pub(crate) fn prometheus_download_url(version: &str, architecture: Architecture) -> String {
303 format!(
304 "https://github.com/prometheus/prometheus/releases/download/v{version}/prometheus-{version}.linux-{arch}.tar.gz",
305 arch = architecture.as_str()
306 )
307}
308
309pub(crate) fn grafana_download_url(version: &str, architecture: Architecture) -> String {
311 format!(
312 "https://dl.grafana.com/oss/release/grafana_{version}_{arch}.deb",
313 arch = architecture.as_str()
314 )
315}
316
317pub(crate) fn loki_download_url(version: &str, architecture: Architecture) -> String {
319 format!(
320 "https://github.com/grafana/loki/releases/download/v{version}/loki-linux-{arch}.zip",
321 arch = architecture.as_str()
322 )
323}
324
325pub(crate) fn pyroscope_download_url(version: &str, architecture: Architecture) -> String {
327 format!(
328 "https://github.com/grafana/pyroscope/releases/download/v{version}/pyroscope_{version}_linux_{arch}.tar.gz",
329 arch = architecture.as_str()
330 )
331}
332
333pub(crate) fn tempo_download_url(version: &str, architecture: Architecture) -> String {
335 format!(
336 "https://github.com/grafana/tempo/releases/download/v{version}/tempo_{version}_linux_{arch}.tar.gz",
337 arch = architecture.as_str()
338 )
339}
340
341pub(crate) fn node_exporter_download_url(version: &str, architecture: Architecture) -> String {
343 format!(
344 "https://github.com/prometheus/node_exporter/releases/download/v{version}/node_exporter-{version}.linux-{arch}.tar.gz",
345 arch = architecture.as_str()
346 )
347}
348
349pub(crate) fn promtail_download_url(version: &str, architecture: Architecture) -> String {
351 format!(
352 "https://github.com/grafana/loki/releases/download/v{version}/promtail-linux-{arch}.zip",
353 arch = architecture.as_str()
354 )
355}
356
357pub(crate) fn samply_download_url(version: &str, architecture: Architecture) -> String {
359 let arch = match architecture {
360 Architecture::Arm64 => "aarch64",
361 Architecture::X86_64 => "x86_64",
362 };
363 format!(
364 "https://github.com/mstange/samply/releases/download/samply-v{version}/samply-{arch}-unknown-linux-gnu.tar.xz"
365 )
366}
367
368pub(crate) fn libjemalloc_download_url(version: &str, architecture: Architecture) -> String {
370 let base = match architecture {
371 Architecture::Arm64 => UBUNTU_ARCHIVE_ARM64,
372 Architecture::X86_64 => UBUNTU_ARCHIVE_X86_64,
373 };
374 format!(
375 "{base}/universe/j/jemalloc/libjemalloc2_{version}_{arch}.deb",
376 arch = architecture.as_str()
377 )
378}
379
380pub(crate) fn logrotate_download_url(version: &str, architecture: Architecture) -> String {
382 let base = match architecture {
383 Architecture::Arm64 => UBUNTU_ARCHIVE_ARM64,
384 Architecture::X86_64 => UBUNTU_ARCHIVE_X86_64,
385 };
386 format!(
387 "{base}/main/l/logrotate/logrotate_{version}_{arch}.deb",
388 arch = architecture.as_str()
389 )
390}
391
392pub(crate) fn libfontconfig_download_url(version: &str, architecture: Architecture) -> String {
394 let base = match architecture {
395 Architecture::Arm64 => UBUNTU_ARCHIVE_ARM64,
396 Architecture::X86_64 => UBUNTU_ARCHIVE_X86_64,
397 };
398 format!(
399 "{base}/main/f/fontconfig/libfontconfig1_{version}_{arch}.deb",
400 arch = architecture.as_str()
401 )
402}
403
404pub(crate) fn fontconfig_config_download_url(version: &str, architecture: Architecture) -> String {
406 let base = match architecture {
407 Architecture::Arm64 => UBUNTU_ARCHIVE_ARM64,
408 Architecture::X86_64 => UBUNTU_ARCHIVE_X86_64,
409 };
410 format!(
411 "{base}/main/f/fontconfig/fontconfig-config_{version}_{arch}.deb",
412 arch = architecture.as_str()
413 )
414}
415
416pub(crate) fn unzip_download_url(version: &str, architecture: Architecture) -> String {
418 let base = match architecture {
419 Architecture::Arm64 => UBUNTU_ARCHIVE_ARM64,
420 Architecture::X86_64 => UBUNTU_ARCHIVE_X86_64,
421 };
422 format!(
423 "{base}/main/u/unzip/unzip_{version}_{arch}.deb",
424 arch = architecture.as_str()
425 )
426}
427
428pub(crate) fn adduser_download_url(version: &str) -> String {
430 format!("{UBUNTU_ARCHIVE_X86_64}/main/a/adduser/adduser_{version}_all.deb")
431}
432
433pub(crate) fn fonts_dejavu_mono_download_url(version: &str) -> String {
435 format!("{UBUNTU_ARCHIVE_X86_64}/main/f/fonts-dejavu/fonts-dejavu-mono_{version}_all.deb")
436}
437
438pub(crate) fn fonts_dejavu_core_download_url(version: &str) -> String {
440 format!("{UBUNTU_ARCHIVE_X86_64}/main/f/fonts-dejavu/fonts-dejavu-core_{version}_all.deb")
441}
442
443pub(crate) fn musl_download_url(version: &str, architecture: Architecture) -> String {
444 let base = match architecture {
445 Architecture::Arm64 => UBUNTU_ARCHIVE_ARM64,
446 Architecture::X86_64 => UBUNTU_ARCHIVE_X86_64,
447 };
448 format!(
449 "{base}/universe/m/musl/musl_{version}_{arch}.deb",
450 arch = architecture.as_str()
451 )
452}
453
454pub const DATASOURCES_YML: &str = r#"
456apiVersion: 1
457datasources:
458 - name: Prometheus
459 type: prometheus
460 url: http://localhost:9090
461 access: proxy
462 isDefault: true
463 - name: Loki
464 type: loki
465 url: http://localhost:3100
466 access: proxy
467 isDefault: false
468 - name: Tempo
469 type: tempo
470 url: http://localhost:3200
471 access: proxy
472 isDefault: false
473 - name: Pyroscope
474 type: grafana-pyroscope-datasource
475 url: http://localhost:4040
476 access: proxy
477 isDefault: false
478"#;
479
480pub const ALL_YML: &str = r#"
482apiVersion: 1
483providers:
484 - name: 'default'
485 orgId: 1
486 folder: ''
487 type: file
488 options:
489 path: /var/lib/grafana/dashboards
490"#;
491
492pub const PROMETHEUS_SERVICE: &str = r#"[Unit]
494Description=Prometheus Monitoring Service
495After=network.target
496
497[Service]
498ExecStart=/opt/prometheus/prometheus --config.file=/opt/prometheus/prometheus.yml --storage.tsdb.path=/opt/prometheus/data
499TimeoutStopSec=60
500Restart=always
501User=ubuntu
502LimitNOFILE=infinity
503
504[Install]
505WantedBy=multi-user.target
506"#;
507
508pub const PROMTAIL_SERVICE: &str = r#"[Unit]
510Description=Promtail Log Forwarder
511After=network.target
512
513[Service]
514ExecStart=/opt/promtail/promtail -config.file=/etc/promtail/promtail.yml
515TimeoutStopSec=60
516Restart=always
517User=ubuntu
518LimitNOFILE=infinity
519
520[Install]
521WantedBy=multi-user.target
522"#;
523
524pub const LOKI_SERVICE: &str = r#"[Unit]
526Description=Loki Log Aggregation Service
527After=network.target
528
529[Service]
530ExecStart=/opt/loki/loki -config.file=/etc/loki/loki.yml
531TimeoutStopSec=60
532Restart=always
533User=ubuntu
534LimitNOFILE=infinity
535
536[Install]
537WantedBy=multi-user.target
538"#;
539
540pub const LOKI_CONFIG: &str = r#"
542auth_enabled: false
543target: all
544server:
545 http_listen_port: 3100
546 grpc_listen_port: 9095
547common:
548 ring:
549 kvstore:
550 store: inmemory
551 replication_factor: 1
552 instance_addr: 127.0.0.1
553schema_config:
554 configs:
555 - from: 2020-10-24
556 store: tsdb
557 object_store: filesystem
558 schema: v13
559 index:
560 prefix: index_
561 period: 24h
562storage_config:
563 tsdb_shipper:
564 active_index_directory: /loki/index
565 cache_location: /loki/index_cache
566 filesystem:
567 directory: /loki/chunks
568table_manager:
569 retention_deletes_enabled: true
570 retention_period: 12h
571compactor:
572 working_directory: /loki/compactor
573ingester:
574 wal:
575 dir: /loki/wal
576"#;
577
578pub const PYROSCOPE_CONFIG: &str = r#"
580target: all
581server:
582 http_listen_port: 4040
583 grpc_listen_port: 0
584pyroscopedb:
585 data_path: /var/lib/pyroscope
586self_profiling:
587 disable_push: true
588"#;
589
590pub const PYROSCOPE_SERVICE: &str = r#"[Unit]
592Description=Pyroscope Profiling Service
593After=network.target
594
595[Service]
596ExecStart=/opt/pyroscope/pyroscope --config.file=/etc/pyroscope/pyroscope.yml
597TimeoutStopSec=60
598Restart=always
599User=ubuntu
600LimitNOFILE=infinity
601
602[Install]
603WantedBy=multi-user.target
604"#;
605
606pub const TEMPO_SERVICE: &str = r#"[Unit]
608Description=Tempo Tracing Service
609After=network.target
610[Service]
611ExecStart=/opt/tempo/tempo -config.file=/etc/tempo/tempo.yml
612TimeoutStopSec=60
613Restart=always
614User=ubuntu
615LimitNOFILE=infinity
616[Install]
617WantedBy=multi-user.target
618"#;
619
620pub const TEMPO_CONFIG: &str = r#"
622server:
623 grpc_listen_port: 9096
624 http_listen_port: 3200
625distributor:
626 receivers:
627 otlp:
628 protocols:
629 http:
630 endpoint: "0.0.0.0:4318"
631storage:
632 trace:
633 backend: local
634 local:
635 path: /tempo/traces
636 wal:
637 path: /tempo/wal
638ingester:
639 max_block_duration: 1h
640compactor:
641 compaction:
642 block_retention: 1h
643 compaction_cycle: 1h
644"#;
645
646pub struct MonitoringUrls {
648 pub prometheus_bin: String,
649 pub grafana_bin: String,
650 pub loki_bin: String,
651 pub pyroscope_bin: String,
652 pub tempo_bin: String,
653 pub node_exporter_bin: String,
654 pub fonts_dejavu_mono_deb: String,
655 pub fonts_dejavu_core_deb: String,
656 pub fontconfig_config_deb: String,
657 pub libfontconfig_deb: String,
658 pub unzip_deb: String,
659 pub adduser_deb: String,
660 pub musl_deb: String,
661 pub prometheus_config: String,
662 pub datasources_yml: String,
663 pub all_yml: String,
664 pub dashboard: String,
665 pub loki_yml: String,
666 pub pyroscope_yml: String,
667 pub tempo_yml: String,
668 pub prometheus_service: String,
669 pub loki_service: String,
670 pub pyroscope_service: String,
671 pub tempo_service: String,
672 pub node_exporter_service: String,
673}
674
675pub(crate) fn install_monitoring_download_cmd(urls: &MonitoringUrls) -> String {
677 format!(
678 r#"
679# Clean up any previous download artifacts (allows retries to re-download fresh copies)
680rm -f /home/ubuntu/prometheus.tar.gz /home/ubuntu/loki.zip /home/ubuntu/pyroscope.tar.gz \
681 /home/ubuntu/tempo.tar.gz /home/ubuntu/node_exporter.tar.gz /home/ubuntu/fonts-dejavu-mono.deb \
682 /home/ubuntu/fonts-dejavu-core.deb /home/ubuntu/fontconfig-config.deb /home/ubuntu/libfontconfig1.deb \
683 /home/ubuntu/unzip.deb /home/ubuntu/adduser.deb /home/ubuntu/musl.deb
684rm -rf /home/ubuntu/prometheus-* /home/ubuntu/loki-linux-* /home/ubuntu/pyroscope \
685 /home/ubuntu/tempo /home/ubuntu/node_exporter-*
686
687# Unmask services in case previous attempt left them masked
688sudo systemctl unmask prometheus loki pyroscope tempo node_exporter grafana-server 2>/dev/null || true
689
690# Download all files from S3 concurrently via pre-signed URLs
691{WGET} -O /home/ubuntu/prometheus.tar.gz '{}' &
692{WGET} -O /home/ubuntu/grafana.deb '{}' &
693{WGET} -O /home/ubuntu/loki.zip '{}' &
694{WGET} -O /home/ubuntu/pyroscope.tar.gz '{}' &
695{WGET} -O /home/ubuntu/tempo.tar.gz '{}' &
696{WGET} -O /home/ubuntu/node_exporter.tar.gz '{}' &
697{WGET} -O /home/ubuntu/fonts-dejavu-mono.deb '{}' &
698{WGET} -O /home/ubuntu/fonts-dejavu-core.deb '{}' &
699{WGET} -O /home/ubuntu/fontconfig-config.deb '{}' &
700{WGET} -O /home/ubuntu/libfontconfig1.deb '{}' &
701{WGET} -O /home/ubuntu/unzip.deb '{}' &
702{WGET} -O /home/ubuntu/adduser.deb '{}' &
703{WGET} -O /home/ubuntu/musl.deb '{}' &
704{WGET} -O /home/ubuntu/prometheus.yml '{}' &
705{WGET} -O /home/ubuntu/datasources.yml '{}' &
706{WGET} -O /home/ubuntu/all.yml '{}' &
707{WGET} -O /home/ubuntu/dashboard.json '{}' &
708{WGET} -O /home/ubuntu/loki.yml '{}' &
709{WGET} -O /home/ubuntu/pyroscope.yml '{}' &
710{WGET} -O /home/ubuntu/tempo.yml '{}' &
711{WGET} -O /home/ubuntu/prometheus.service '{}' &
712{WGET} -O /home/ubuntu/loki.service '{}' &
713{WGET} -O /home/ubuntu/pyroscope.service '{}' &
714{WGET} -O /home/ubuntu/tempo.service '{}' &
715{WGET} -O /home/ubuntu/node_exporter.service '{}' &
716wait
717
718# Verify all downloads succeeded
719for f in prometheus.tar.gz grafana.deb loki.zip pyroscope.tar.gz tempo.tar.gz node_exporter.tar.gz \
720 fonts-dejavu-mono.deb fonts-dejavu-core.deb fontconfig-config.deb libfontconfig1.deb unzip.deb adduser.deb musl.deb prometheus.yml datasources.yml all.yml dashboard.json \
721 loki.yml pyroscope.yml tempo.yml prometheus.service loki.service pyroscope.service \
722 tempo.service node_exporter.service; do
723 if [ ! -f "/home/ubuntu/$f" ]; then
724 echo "ERROR: Failed to download $f" >&2
725 exit 1
726 fi
727done
728"#,
729 urls.prometheus_bin,
730 urls.grafana_bin,
731 urls.loki_bin,
732 urls.pyroscope_bin,
733 urls.tempo_bin,
734 urls.node_exporter_bin,
735 urls.fonts_dejavu_mono_deb,
736 urls.fonts_dejavu_core_deb,
737 urls.fontconfig_config_deb,
738 urls.libfontconfig_deb,
739 urls.unzip_deb,
740 urls.adduser_deb,
741 urls.musl_deb,
742 urls.prometheus_config,
743 urls.datasources_yml,
744 urls.all_yml,
745 urls.dashboard,
746 urls.loki_yml,
747 urls.pyroscope_yml,
748 urls.tempo_yml,
749 urls.prometheus_service,
750 urls.loki_service,
751 urls.pyroscope_service,
752 urls.tempo_service,
753 urls.node_exporter_service,
754 )
755}
756
757pub(crate) fn install_monitoring_setup_cmd(
759 prometheus_version: &str,
760 architecture: Architecture,
761) -> String {
762 let arch = architecture.as_str();
763 format!(
764 r#"set -e
765
766# Enable BBR congestion control
767echo -e "net.core.default_qdisc=fq\nnet.ipv4.tcp_congestion_control=bbr" | sudo tee /etc/sysctl.d/99-bbr.conf >/dev/null && sudo sysctl -p /etc/sysctl.d/99-bbr.conf
768
769# Install deb packages
770sudo dpkg -i /home/ubuntu/unzip.deb
771sudo dpkg -i /home/ubuntu/adduser.deb
772
773# Install Prometheus
774sudo mkdir -p /opt/prometheus /opt/prometheus/data
775sudo chown -R ubuntu:ubuntu /opt/prometheus
776tar xvfz /home/ubuntu/prometheus.tar.gz -C /home/ubuntu
777sudo rm -rf /opt/prometheus/prometheus-{prometheus_version}.linux-{arch}
778sudo mv /home/ubuntu/prometheus-{prometheus_version}.linux-{arch} /opt/prometheus/prometheus-{prometheus_version}.linux-{arch}
779sudo ln -sf /opt/prometheus/prometheus-{prometheus_version}.linux-{arch}/prometheus /opt/prometheus/prometheus
780sudo chmod +x /opt/prometheus/prometheus
781
782# Install Grafana dependencies (fonts-dejavu-mono, fonts-dejavu-core, fontconfig-config, libfontconfig1, musl) and Grafana
783sudo dpkg -i /home/ubuntu/fonts-dejavu-mono.deb
784sudo dpkg -i /home/ubuntu/fonts-dejavu-core.deb
785sudo dpkg -i /home/ubuntu/fontconfig-config.deb
786sudo dpkg -i /home/ubuntu/libfontconfig1.deb
787sudo dpkg -i /home/ubuntu/musl.deb
788sudo dpkg -i /home/ubuntu/grafana.deb
789
790# Install Loki
791sudo mkdir -p /opt/loki /loki/index /loki/index_cache /loki/chunks /loki/compactor /loki/wal
792sudo chown -R ubuntu:ubuntu /opt/loki /loki
793unzip -o /home/ubuntu/loki.zip -d /home/ubuntu
794sudo rm -f /opt/loki/loki
795sudo mv /home/ubuntu/loki-linux-{arch} /opt/loki/loki
796sudo chmod +x /opt/loki/loki
797
798# Install Pyroscope
799sudo mkdir -p /opt/pyroscope /var/lib/pyroscope
800sudo chown -R ubuntu:ubuntu /opt/pyroscope /var/lib/pyroscope
801tar xvfz /home/ubuntu/pyroscope.tar.gz -C /home/ubuntu
802sudo rm -f /opt/pyroscope/pyroscope
803sudo mv /home/ubuntu/pyroscope /opt/pyroscope/pyroscope
804sudo chmod +x /opt/pyroscope/pyroscope
805
806# Install Tempo
807sudo mkdir -p /opt/tempo /tempo/traces /tempo/wal
808sudo chown -R ubuntu:ubuntu /opt/tempo /tempo
809tar xvfz /home/ubuntu/tempo.tar.gz -C /home/ubuntu
810sudo rm -f /opt/tempo/tempo
811sudo mv /home/ubuntu/tempo /opt/tempo/tempo
812sudo chmod +x /opt/tempo/tempo
813
814# Install Node Exporter
815sudo mkdir -p /opt/node_exporter
816sudo chown -R ubuntu:ubuntu /opt/node_exporter
817tar xvfz /home/ubuntu/node_exporter.tar.gz -C /home/ubuntu
818sudo rm -rf /opt/node_exporter/node_exporter-*.linux-{arch}
819sudo mv /home/ubuntu/node_exporter-*.linux-{arch} /opt/node_exporter/
820sudo ln -sf /opt/node_exporter/node_exporter-*.linux-{arch}/node_exporter /opt/node_exporter/node_exporter
821sudo chmod +x /opt/node_exporter/node_exporter
822
823# Configure Grafana
824sudo sed -i '/^\[auth.anonymous\]$/,/^\[/ {{ /^; *enabled = /s/.*/enabled = true/; /^; *org_role = /s/.*/org_role = Admin/ }}' /etc/grafana/grafana.ini
825sudo mkdir -p /etc/grafana/provisioning/datasources /etc/grafana/provisioning/dashboards /var/lib/grafana/dashboards
826
827# Install configuration files
828sudo mv /home/ubuntu/prometheus.yml /opt/prometheus/prometheus.yml
829sudo mv /home/ubuntu/datasources.yml /etc/grafana/provisioning/datasources/datasources.yml
830sudo mv /home/ubuntu/all.yml /etc/grafana/provisioning/dashboards/all.yml
831sudo mv /home/ubuntu/dashboard.json /var/lib/grafana/dashboards/dashboard.json
832sudo mkdir -p /etc/loki
833sudo mv /home/ubuntu/loki.yml /etc/loki/loki.yml
834sudo chown root:root /etc/loki/loki.yml
835sudo mkdir -p /etc/pyroscope
836sudo mv /home/ubuntu/pyroscope.yml /etc/pyroscope/pyroscope.yml
837sudo chown root:root /etc/pyroscope/pyroscope.yml
838sudo mkdir -p /etc/tempo
839sudo mv /home/ubuntu/tempo.yml /etc/tempo/tempo.yml
840sudo chown root:root /etc/tempo/tempo.yml
841
842# Install service files
843sudo mv /home/ubuntu/prometheus.service /etc/systemd/system/prometheus.service
844sudo mv /home/ubuntu/loki.service /etc/systemd/system/loki.service
845sudo mv /home/ubuntu/pyroscope.service /etc/systemd/system/pyroscope.service
846sudo mv /home/ubuntu/tempo.service /etc/systemd/system/tempo.service
847sudo mv /home/ubuntu/node_exporter.service /etc/systemd/system/node_exporter.service
848"#
849 )
850}
851
852pub const fn start_monitoring_services_cmd() -> &'static str {
854 r#"set -e
855
856sudo chown -R grafana:grafana /etc/grafana /var/lib/grafana
857
858# Start services
859sudo systemctl daemon-reload
860sudo systemctl start node_exporter
861sudo systemctl enable node_exporter
862sudo systemctl start prometheus
863sudo systemctl enable prometheus
864sudo systemctl start loki
865sudo systemctl enable loki
866sudo systemctl start pyroscope
867sudo systemctl enable pyroscope
868sudo systemctl start tempo
869sudo systemctl enable tempo
870sudo systemctl restart grafana-server
871sudo systemctl enable grafana-server
872"#
873}
874
875pub struct InstanceUrls {
877 pub binary: String,
878 pub config: String,
879 pub hosts: String,
880 pub promtail_bin: String,
881 pub promtail_config: String,
882 pub promtail_service: String,
883 pub node_exporter_bin: String,
884 pub node_exporter_service: String,
885 pub binary_service: String,
886 pub logrotate_conf: String,
887 pub pyroscope_script: String,
888 pub pyroscope_service: String,
889 pub pyroscope_timer: String,
890 pub libjemalloc_deb: String,
891 pub logrotate_deb: String,
892 pub unzip_deb: String,
893}
894
895pub(crate) const fn install_binary_apt_cmd(profiling: bool) -> Option<&'static str> {
898 if profiling {
899 Some(
900 r#"set -e
901sudo apt-get update -y
902sudo apt-get install -y linux-tools-common linux-tools-generic linux-tools-$(uname -r)
903"#,
904 )
905 } else {
906 None
907 }
908}
909
910pub(crate) fn install_binary_download_cmd(urls: &InstanceUrls) -> String {
912 format!(
913 r#"
914# Clean up any previous download artifacts (allows retries to re-download fresh copies)
915rm -f /home/ubuntu/promtail.zip /home/ubuntu/node_exporter.tar.gz \
916 /home/ubuntu/libjemalloc2.deb /home/ubuntu/logrotate.deb /home/ubuntu/unzip.deb
917rm -rf /home/ubuntu/promtail-linux-* /home/ubuntu/node_exporter-*
918
919# Unmask services in case previous attempt left them masked
920sudo systemctl unmask promtail node_exporter binary 2>/dev/null || true
921
922# Download all files from S3 concurrently via pre-signed URLs
923{WGET} -O /home/ubuntu/binary '{}' &
924{WGET} -O /home/ubuntu/config.conf '{}' &
925{WGET} -O /home/ubuntu/hosts.yaml '{}' &
926{WGET} -O /home/ubuntu/promtail.zip '{}' &
927{WGET} -O /home/ubuntu/promtail.yml '{}' &
928{WGET} -O /home/ubuntu/promtail.service '{}' &
929{WGET} -O /home/ubuntu/node_exporter.tar.gz '{}' &
930{WGET} -O /home/ubuntu/node_exporter.service '{}' &
931{WGET} -O /home/ubuntu/binary.service '{}' &
932{WGET} -O /home/ubuntu/logrotate.conf '{}' &
933{WGET} -O /home/ubuntu/pyroscope-agent.sh '{}' &
934{WGET} -O /home/ubuntu/pyroscope-agent.service '{}' &
935{WGET} -O /home/ubuntu/pyroscope-agent.timer '{}' &
936{WGET} -O /home/ubuntu/libjemalloc2.deb '{}' &
937{WGET} -O /home/ubuntu/logrotate.deb '{}' &
938{WGET} -O /home/ubuntu/unzip.deb '{}' &
939wait
940
941# Verify all downloads succeeded
942for f in binary config.conf hosts.yaml promtail.zip promtail.yml promtail.service \
943 node_exporter.tar.gz node_exporter.service binary.service logrotate.conf \
944 pyroscope-agent.sh pyroscope-agent.service pyroscope-agent.timer \
945 libjemalloc2.deb logrotate.deb unzip.deb; do
946 if [ ! -f "/home/ubuntu/$f" ]; then
947 echo "ERROR: Failed to download $f" >&2
948 exit 1
949 fi
950done
951"#,
952 urls.binary,
953 urls.config,
954 urls.hosts,
955 urls.promtail_bin,
956 urls.promtail_config,
957 urls.promtail_service,
958 urls.node_exporter_bin,
959 urls.node_exporter_service,
960 urls.binary_service,
961 urls.logrotate_conf,
962 urls.pyroscope_script,
963 urls.pyroscope_service,
964 urls.pyroscope_timer,
965 urls.libjemalloc_deb,
966 urls.logrotate_deb,
967 urls.unzip_deb,
968 )
969}
970
971pub(crate) fn install_binary_setup_cmd(profiling: bool, architecture: Architecture) -> String {
973 let arch = architecture.as_str();
974 let perf_setup = if profiling {
975 r#"
976# Setup pyroscope agent (perf symlink must be created after linux-tools installed via apt)
977sudo ln -sf "$(find /usr/lib/linux-tools/*/perf | head -1)" /usr/local/bin/perf
978sudo chmod +x /home/ubuntu/pyroscope-agent.sh
979sudo mv /home/ubuntu/pyroscope-agent.service /etc/systemd/system/pyroscope-agent.service
980sudo mv /home/ubuntu/pyroscope-agent.timer /etc/systemd/system/pyroscope-agent.timer
981"#
982 } else {
983 ""
984 };
985 let pyroscope_enable = if profiling {
986 "\nsudo systemctl enable --now pyroscope-agent.timer\n"
987 } else {
988 ""
989 };
990 format!(
991 r#"set -e
992
993# Enable BBR congestion control
994echo -e "net.core.default_qdisc=fq\nnet.ipv4.tcp_congestion_control=bbr" | sudo tee /etc/sysctl.d/99-bbr.conf >/dev/null && sudo sysctl -p /etc/sysctl.d/99-bbr.conf
995
996# Install deb packages
997sudo dpkg -i /home/ubuntu/unzip.deb
998sudo dpkg -i /home/ubuntu/libjemalloc2.deb
999sudo dpkg -i /home/ubuntu/logrotate.deb
1000
1001# Install Promtail
1002sudo mkdir -p /opt/promtail /etc/promtail
1003sudo chown -R ubuntu:ubuntu /opt/promtail
1004unzip -o /home/ubuntu/promtail.zip -d /home/ubuntu
1005sudo rm -f /opt/promtail/promtail
1006sudo mv /home/ubuntu/promtail-linux-{arch} /opt/promtail/promtail
1007sudo chmod +x /opt/promtail/promtail
1008sudo mv /home/ubuntu/promtail.yml /etc/promtail/promtail.yml
1009sudo mv /home/ubuntu/promtail.service /etc/systemd/system/promtail.service
1010sudo chown root:root /etc/promtail/promtail.yml
1011
1012# Install Node Exporter
1013sudo mkdir -p /opt/node_exporter
1014sudo chown -R ubuntu:ubuntu /opt/node_exporter
1015tar xvfz /home/ubuntu/node_exporter.tar.gz -C /home/ubuntu
1016sudo rm -rf /opt/node_exporter/node_exporter-*.linux-{arch}
1017sudo mv /home/ubuntu/node_exporter-*.linux-{arch} /opt/node_exporter/
1018sudo ln -sf /opt/node_exporter/node_exporter-*.linux-{arch}/node_exporter /opt/node_exporter/node_exporter
1019sudo chmod +x /opt/node_exporter/node_exporter
1020sudo mv /home/ubuntu/node_exporter.service /etc/systemd/system/node_exporter.service
1021
1022# Setup binary
1023chmod +x /home/ubuntu/binary
1024sudo touch /var/log/binary.log && sudo chown ubuntu:ubuntu /var/log/binary.log
1025sudo mv /home/ubuntu/binary.service /etc/systemd/system/binary.service
1026
1027# Setup logrotate
1028sudo mv /home/ubuntu/logrotate.conf /etc/logrotate.d/binary
1029sudo chown root:root /etc/logrotate.d/binary
1030echo "0 * * * * /usr/sbin/logrotate /etc/logrotate.d/binary" | crontab -
1031{perf_setup}
1032# Start services
1033sudo systemctl daemon-reload
1034sudo systemctl enable --now promtail
1035sudo systemctl enable --now node_exporter
1036sudo systemctl enable --now binary{pyroscope_enable}"#
1037 )
1038}
1039
1040pub fn promtail_config(
1042 monitoring_private_ip: &str,
1043 instance_name: &str,
1044 ip: &str,
1045 region: &str,
1046 arch: &str,
1047) -> String {
1048 format!(
1049 r#"
1050server:
1051 http_listen_port: 9080
1052 grpc_listen_port: 0
1053positions:
1054 filename: /tmp/positions.yaml
1055clients:
1056 - url: http://{monitoring_private_ip}:3100/loki/api/v1/push
1057scrape_configs:
1058 - job_name: binary_logs
1059 static_configs:
1060 - targets:
1061 - localhost
1062 labels:
1063 deployer_name: {instance_name}
1064 deployer_ip: {ip}
1065 deployer_region: {region}
1066 deployer_arch: {arch}
1067 __path__: /var/log/binary.log
1068"#
1069 )
1070}
1071
1072pub const NODE_EXPORTER_SERVICE: &str = r#"[Unit]
1074Description=Node Exporter
1075After=network.target
1076
1077[Service]
1078ExecStart=/opt/node_exporter/node_exporter
1079TimeoutStopSec=60
1080Restart=always
1081User=ubuntu
1082LimitNOFILE=infinity
1083
1084[Install]
1085WantedBy=multi-user.target
1086"#;
1087
1088pub fn generate_prometheus_config(instances: &[(&str, &str, &str, &str)]) -> String {
1090 let mut config = String::from(
1091 r#"
1092global:
1093 scrape_interval: 15s
1094scrape_configs:
1095 - job_name: 'monitoring_system'
1096 static_configs:
1097 - targets: ['localhost:9100']
1098"#,
1099 );
1100 for (name, ip, region, arch) in instances {
1101 config.push_str(&format!(
1102 r#"
1103 - job_name: '{name}_binary'
1104 static_configs:
1105 - targets: ['{ip}:9090']
1106 labels:
1107 deployer_name: '{name}'
1108 deployer_ip: '{ip}'
1109 deployer_region: '{region}'
1110 deployer_arch: '{arch}'
1111 - job_name: '{name}_system'
1112 static_configs:
1113 - targets: ['{ip}:9100']
1114 labels:
1115 deployer_name: '{name}'
1116 deployer_ip: '{ip}'
1117 deployer_region: '{region}'
1118 deployer_arch: '{arch}'
1119"#
1120 ));
1121 }
1122 config
1123}
1124
1125pub const LOGROTATE_CONF: &str = r#"
1127/var/log/binary.log {
1128 rotate 0
1129 copytruncate
1130 missingok
1131 notifempty
1132}
1133"#;
1134
1135pub(crate) fn binary_service(architecture: Architecture) -> String {
1137 let lib_arch = architecture.linux_lib();
1138 format!(
1139 r#"[Unit]
1140Description=Deployed Binary Service
1141After=network.target
1142
1143[Service]
1144Environment="LD_PRELOAD=/usr/lib/{lib_arch}/libjemalloc.so.2"
1145ExecStart=/home/ubuntu/binary --hosts=/home/ubuntu/hosts.yaml --config=/home/ubuntu/config.conf
1146TimeoutStopSec=60
1147Restart=always
1148User=ubuntu
1149LimitNOFILE=infinity
1150StandardOutput=append:/var/log/binary.log
1151StandardError=append:/var/log/binary.log
1152
1153[Install]
1154WantedBy=multi-user.target
1155"#
1156 )
1157}
1158
1159pub fn generate_pyroscope_script(
1161 monitoring_private_ip: &str,
1162 name: &str,
1163 ip: &str,
1164 region: &str,
1165 arch: &str,
1166) -> String {
1167 format!(
1168 r#"#!/bin/bash
1169set -e
1170
1171SERVICE_NAME="binary.service"
1172PERF_DATA_FILE="/tmp/perf.data"
1173PERF_STACK_FILE="/tmp/perf.stack"
1174PROFILE_DURATION=60 # seconds
1175PERF_FREQ=100 # Hz
1176
1177# Construct the Pyroscope application name with tags (URL-encoded)
1178RAW_APP_NAME="binary{{deployer_name={name},deployer_ip={ip},deployer_region={region},deployer_arch={arch}}}"
1179APP_NAME=$(printf '%s' "$RAW_APP_NAME" | python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.stdin.read()))")
1180
1181# Get the PID of the binary service
1182PID=$(systemctl show --property MainPID ${{SERVICE_NAME}} | cut -d= -f2)
1183if [ -z "$PID" ] || [ "$PID" -eq 0 ]; then
1184 echo "Error: Could not get PID for ${{SERVICE_NAME}}." >&2
1185 exit 1
1186fi
1187
1188# Record performance data
1189echo "Recording perf data for PID ${{PID}}..."
1190sudo perf record -F ${{PERF_FREQ}} -p ${{PID}} -o ${{PERF_DATA_FILE}} -g --call-graph fp -- sleep ${{PROFILE_DURATION}}
1191
1192# Generate folded stack report
1193echo "Generating folded stack report..."
1194sudo perf report -i ${{PERF_DATA_FILE}} --stdio --no-children -g folded,0,caller,count -s comm | \
1195 awk '/^[0-9]+\.[0-9]+%/ {{ comm = $2 }} /^[0-9]/ {{ print comm ";" substr($0, index($0, $2)), $1 }}' > ${{PERF_STACK_FILE}}
1196
1197# Check if stack file is empty (perf might fail silently sometimes)
1198if [ ! -s "${{PERF_STACK_FILE}}" ]; then
1199 echo "Warning: ${{PERF_STACK_FILE}} is empty. Skipping upload." >&2
1200 # Clean up empty perf.data
1201 sudo rm -f ${{PERF_DATA_FILE}} ${{PERF_STACK_FILE}}
1202 exit 0
1203fi
1204
1205# Calculate timestamps
1206UNTIL_TS=$(date +%s)
1207FROM_TS=$((UNTIL_TS - PROFILE_DURATION))
1208
1209# Upload to Pyroscope
1210echo "Uploading profile to Pyroscope at {monitoring_private_ip}..."
1211wget --post-file="${{PERF_STACK_FILE}}" \
1212 --header="Content-Type: text/plain" \
1213 --quiet \
1214 -O /dev/null \
1215 "http://{monitoring_private_ip}:4040/ingest?name=${{APP_NAME}}&format=folded&units=samples&aggregationType=sum&sampleType=cpu&from=${{FROM_TS}}&until=${{UNTIL_TS}}&spyName=perf"
1216
1217echo "Profile upload complete."
1218sudo rm -f ${{PERF_DATA_FILE}} ${{PERF_STACK_FILE}}
1219"#
1220 )
1221}
1222
1223pub const PYROSCOPE_AGENT_SERVICE: &str = r#"[Unit]
1225Description=Pyroscope Agent (Perf Script Runner)
1226Wants=network-online.target
1227After=network-online.target binary.service
1228
1229[Service]
1230Type=oneshot
1231User=ubuntu
1232ExecStart=/home/ubuntu/pyroscope-agent.sh
1233
1234[Install]
1235WantedBy=multi-user.target
1236"#;
1237
1238pub const PYROSCOPE_AGENT_TIMER: &str = r#"[Unit]
1240Description=Run Pyroscope Agent periodically
1241
1242[Timer]
1243# Wait a bit after boot before the first run
1244OnBootSec=2min
1245# Run roughly every minute after the last run finished
1246OnUnitInactiveSec=1min
1247Unit=pyroscope-agent.service
1248# Randomize the delay to avoid thundering herd
1249RandomizedDelaySec=10s
1250
1251[Install]
1252WantedBy=timers.target
1253"#;
1254
1255#[cfg(test)]
1256mod tests {
1257 use super::*;
1258
1259 #[test]
1260 fn test_binary_s3_keys_arm64() {
1261 let arch = Architecture::Arm64;
1262 assert_eq!(
1263 prometheus_bin_s3_key("3.2.0", arch),
1264 "tools/binaries/prometheus/3.2.0/linux-arm64/prometheus-3.2.0.linux-arm64.tar.gz"
1265 );
1266 assert_eq!(
1267 grafana_bin_s3_key("11.5.2", arch),
1268 "tools/binaries/grafana/11.5.2/linux-arm64/grafana_11.5.2_arm64.deb"
1269 );
1270 assert_eq!(
1271 loki_bin_s3_key("3.4.2", arch),
1272 "tools/binaries/loki/3.4.2/linux-arm64/loki-linux-arm64.zip"
1273 );
1274 assert_eq!(
1275 pyroscope_bin_s3_key("1.12.0", arch),
1276 "tools/binaries/pyroscope/1.12.0/linux-arm64/pyroscope_1.12.0_linux_arm64.tar.gz"
1277 );
1278 assert_eq!(
1279 tempo_bin_s3_key("2.7.1", arch),
1280 "tools/binaries/tempo/2.7.1/linux-arm64/tempo_2.7.1_linux_arm64.tar.gz"
1281 );
1282 assert_eq!(
1283 node_exporter_bin_s3_key("1.9.0", arch),
1284 "tools/binaries/node-exporter/1.9.0/linux-arm64/node_exporter-1.9.0.linux-arm64.tar.gz"
1285 );
1286 assert_eq!(
1287 promtail_bin_s3_key("3.4.2", arch),
1288 "tools/binaries/promtail/3.4.2/linux-arm64/promtail-linux-arm64.zip"
1289 );
1290 assert_eq!(
1291 libjemalloc_bin_s3_key("5.3.0-2build1", arch),
1292 "tools/binaries/libjemalloc2/5.3.0-2build1/linux-arm64/libjemalloc2_5.3.0-2build1_arm64.deb"
1293 );
1294 assert_eq!(
1295 logrotate_bin_s3_key("3.21.0-2build1", arch),
1296 "tools/binaries/logrotate/3.21.0-2build1/linux-arm64/logrotate_3.21.0-2build1_arm64.deb"
1297 );
1298 assert_eq!(
1299 libfontconfig_bin_s3_key("2.15.0-1.1ubuntu2", arch),
1300 "tools/binaries/libfontconfig1/2.15.0-1.1ubuntu2/linux-arm64/libfontconfig1_2.15.0-1.1ubuntu2_arm64.deb"
1301 );
1302 assert_eq!(
1303 unzip_bin_s3_key("6.0-28ubuntu4", arch),
1304 "tools/binaries/unzip/6.0-28ubuntu4/linux-arm64/unzip_6.0-28ubuntu4_arm64.deb"
1305 );
1306 }
1307
1308 #[test]
1309 fn test_binary_s3_keys_x86_64() {
1310 let arch = Architecture::X86_64;
1311 assert_eq!(
1312 prometheus_bin_s3_key("3.2.0", arch),
1313 "tools/binaries/prometheus/3.2.0/linux-amd64/prometheus-3.2.0.linux-amd64.tar.gz"
1314 );
1315 assert_eq!(
1316 grafana_bin_s3_key("11.5.2", arch),
1317 "tools/binaries/grafana/11.5.2/linux-amd64/grafana_11.5.2_amd64.deb"
1318 );
1319 assert_eq!(
1320 loki_bin_s3_key("3.4.2", arch),
1321 "tools/binaries/loki/3.4.2/linux-amd64/loki-linux-amd64.zip"
1322 );
1323 assert_eq!(
1324 pyroscope_bin_s3_key("1.12.0", arch),
1325 "tools/binaries/pyroscope/1.12.0/linux-amd64/pyroscope_1.12.0_linux_amd64.tar.gz"
1326 );
1327 assert_eq!(
1328 tempo_bin_s3_key("2.7.1", arch),
1329 "tools/binaries/tempo/2.7.1/linux-amd64/tempo_2.7.1_linux_amd64.tar.gz"
1330 );
1331 assert_eq!(
1332 node_exporter_bin_s3_key("1.9.0", arch),
1333 "tools/binaries/node-exporter/1.9.0/linux-amd64/node_exporter-1.9.0.linux-amd64.tar.gz"
1334 );
1335 assert_eq!(
1336 promtail_bin_s3_key("3.4.2", arch),
1337 "tools/binaries/promtail/3.4.2/linux-amd64/promtail-linux-amd64.zip"
1338 );
1339 assert_eq!(
1340 libjemalloc_bin_s3_key("5.3.0-2build1", arch),
1341 "tools/binaries/libjemalloc2/5.3.0-2build1/linux-amd64/libjemalloc2_5.3.0-2build1_amd64.deb"
1342 );
1343 assert_eq!(
1344 logrotate_bin_s3_key("3.21.0-2build1", arch),
1345 "tools/binaries/logrotate/3.21.0-2build1/linux-amd64/logrotate_3.21.0-2build1_amd64.deb"
1346 );
1347 assert_eq!(
1348 libfontconfig_bin_s3_key("2.15.0-1.1ubuntu2", arch),
1349 "tools/binaries/libfontconfig1/2.15.0-1.1ubuntu2/linux-amd64/libfontconfig1_2.15.0-1.1ubuntu2_amd64.deb"
1350 );
1351 assert_eq!(
1352 unzip_bin_s3_key("6.0-28ubuntu4", arch),
1353 "tools/binaries/unzip/6.0-28ubuntu4/linux-amd64/unzip_6.0-28ubuntu4_amd64.deb"
1354 );
1355 }
1356
1357 #[test]
1358 fn test_config_s3_keys() {
1359 let version = DEPLOYER_VERSION;
1360
1361 assert_eq!(
1362 prometheus_service_s3_key(),
1363 format!("tools/configs/{version}/prometheus/service")
1364 );
1365 assert_eq!(
1366 grafana_datasources_s3_key(),
1367 format!("tools/configs/{version}/grafana/datasources.yml")
1368 );
1369 assert_eq!(
1370 grafana_dashboards_s3_key(),
1371 format!("tools/configs/{version}/grafana/all.yml")
1372 );
1373 assert_eq!(
1374 loki_config_s3_key(),
1375 format!("tools/configs/{version}/loki/config.yml")
1376 );
1377 assert_eq!(
1378 loki_service_s3_key(),
1379 format!("tools/configs/{version}/loki/service")
1380 );
1381 assert_eq!(
1382 pyroscope_config_s3_key(),
1383 format!("tools/configs/{version}/pyroscope/config.yml")
1384 );
1385 assert_eq!(
1386 pyroscope_service_s3_key(),
1387 format!("tools/configs/{version}/pyroscope/service")
1388 );
1389 assert_eq!(
1390 tempo_config_s3_key(),
1391 format!("tools/configs/{version}/tempo/config.yml")
1392 );
1393 assert_eq!(
1394 tempo_service_s3_key(),
1395 format!("tools/configs/{version}/tempo/service")
1396 );
1397 assert_eq!(
1398 node_exporter_service_s3_key(),
1399 format!("tools/configs/{version}/node-exporter/service")
1400 );
1401 assert_eq!(
1402 promtail_service_s3_key(),
1403 format!("tools/configs/{version}/promtail/service")
1404 );
1405 assert_eq!(
1406 pyroscope_agent_service_s3_key(),
1407 format!("tools/configs/{version}/pyroscope/agent.service")
1408 );
1409 assert_eq!(
1410 pyroscope_agent_timer_s3_key(),
1411 format!("tools/configs/{version}/pyroscope/agent.timer")
1412 );
1413 assert_eq!(
1414 logrotate_config_s3_key(),
1415 format!("tools/configs/{version}/system/logrotate.conf")
1416 );
1417 assert_eq!(
1418 binary_service_s3_key_for_arch(Architecture::Arm64),
1419 format!("tools/configs/{version}/binary/service-arm64")
1420 );
1421 assert_eq!(
1422 binary_service_s3_key_for_arch(Architecture::X86_64),
1423 format!("tools/configs/{version}/binary/service-amd64")
1424 );
1425 }
1426
1427 #[test]
1428 fn test_deployment_s3_keys() {
1429 let digest = "abc123def456";
1430 assert_eq!(
1431 binary_s3_key("my-tag", digest),
1432 "deployments/my-tag/binaries/abc123def456"
1433 );
1434 assert_eq!(
1435 config_s3_key("my-tag", digest),
1436 "deployments/my-tag/configs/abc123def456"
1437 );
1438 assert_eq!(
1439 hosts_s3_key("my-tag", digest),
1440 "deployments/my-tag/hosts/abc123def456"
1441 );
1442 assert_eq!(
1443 promtail_s3_key("my-tag", digest),
1444 "deployments/my-tag/promtail/abc123def456"
1445 );
1446 assert_eq!(
1447 pyroscope_s3_key("my-tag", digest),
1448 "deployments/my-tag/pyroscope/abc123def456"
1449 );
1450 assert_eq!(
1451 monitoring_s3_key("my-tag", digest),
1452 "deployments/my-tag/monitoring/abc123def456"
1453 );
1454 }
1455}