appydave-tools 0.76.5 â 0.76.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/bin/dam +2 -184
- data/docs/planning/extract-vat-cli/IMPLEMENTATION_PLAN.md +2 -2
- data/lib/appydave/tools/dam/s3_scan_command.rb +191 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools.rb +1 -0
- data/package.json +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f4172ac86ad4f32c89534b2129ffed582137abc47e21fe1fb2e1d18c5a56608e
|
|
4
|
+
data.tar.gz: ed067098e65634fce56abf446313a7f58657dbc7fc45499915cb34d6a9ae5afe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 79f3caf203405a2cf7337da3129595433515c04e6b4f9f1203b70b5ef89e07caa07ac212d6e9bb85244185f5d5d3b8e20f175e01e7587fb1fe1920630dadf8e1
|
|
7
|
+
data.tar.gz: e42dfc787b1331d7fdfbd32c731f13e03f946bf5e2fa9d89f948f9cb59dc393a80e054b075b650d51d72eb7070f846f0253beef5e011cf3c632b8181b5b30f7f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [0.76.5](https://github.com/appydave/appydave-tools/compare/v0.76.4...v0.76.5) (2026-03-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* extract LocalSyncStatus module from VatCLI; add spec ([0672855](https://github.com/appydave/appydave-tools/commit/0672855a25ebcbb2df3f5eea6208f910aed74124))
|
|
7
|
+
* remove redundant rubocop disable directives in LocalSyncStatus ([9050795](https://github.com/appydave/appydave-tools/commit/905079573caf7555771da02b2d9c6ebfc34d1c95))
|
|
8
|
+
* replace format_bytes with FileHelper.format_size; remove duplicate method from VatCLI ([3cd362f](https://github.com/appydave/appydave-tools/commit/3cd362f79342578ddb7a750b9b404851cf4d1eb4))
|
|
9
|
+
* restore youtube_automation_config require removed by micro-cleanup; fix spec brand dir setup ([a5779a7](https://github.com/appydave/appydave-tools/commit/a5779a7b5dab1697b2a21ca3bbece9c0bff340c2))
|
|
10
|
+
|
|
1
11
|
## [0.76.4](https://github.com/appydave/appydave-tools/compare/v0.76.3...v0.76.4) (2026-03-19)
|
|
2
12
|
|
|
3
13
|
|
data/bin/dam
CHANGED
|
@@ -1325,9 +1325,9 @@ class VatCLI
|
|
|
1325
1325
|
brand_arg = args[0]
|
|
1326
1326
|
|
|
1327
1327
|
if all_brands
|
|
1328
|
-
|
|
1328
|
+
Appydave::Tools::Dam::S3ScanCommand.new.scan_all
|
|
1329
1329
|
elsif brand_arg
|
|
1330
|
-
|
|
1330
|
+
Appydave::Tools::Dam::S3ScanCommand.new.scan_single(brand_arg)
|
|
1331
1331
|
else
|
|
1332
1332
|
puts 'Usage: dam s3-scan <brand> [--all]'
|
|
1333
1333
|
puts ''
|
|
@@ -1343,188 +1343,6 @@ class VatCLI
|
|
|
1343
1343
|
puts e.backtrace.first(5).join("\n") if ENV['DEBUG']
|
|
1344
1344
|
exit 1
|
|
1345
1345
|
end
|
|
1346
|
-
|
|
1347
|
-
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
1348
|
-
def scan_single_brand_s3(brand_arg)
|
|
1349
|
-
puts "đ Scanning S3 for #{brand_arg}..."
|
|
1350
|
-
puts ''
|
|
1351
|
-
|
|
1352
|
-
brand_key = brand_arg
|
|
1353
|
-
scanner = Appydave::Tools::Dam::S3Scanner.new(brand_key)
|
|
1354
|
-
|
|
1355
|
-
# Get brand info for S3 path
|
|
1356
|
-
Appydave::Tools::Configuration::Config.configure
|
|
1357
|
-
brand_info = Appydave::Tools::Configuration::Config.brands.get_brand(brand_key)
|
|
1358
|
-
bucket = brand_info.aws.s3_bucket
|
|
1359
|
-
prefix = brand_info.aws.s3_prefix
|
|
1360
|
-
region = brand_info.aws.region
|
|
1361
|
-
|
|
1362
|
-
# Spinner characters for progress
|
|
1363
|
-
spinner_chars = ['â ', 'â ', 'â š', 'â ¸', 'â ŧ', 'â ´', 'â Ļ', 'â §', 'â ', 'â ']
|
|
1364
|
-
spinner_index = 0
|
|
1365
|
-
|
|
1366
|
-
print "đ Scanning s3://#{bucket}/#{prefix}\n"
|
|
1367
|
-
print ' Scanning projects... '
|
|
1368
|
-
|
|
1369
|
-
# Scan all projects with progress callback
|
|
1370
|
-
results = scanner.scan_all_projects(show_progress: false) do |current, total|
|
|
1371
|
-
print "\r Scanning projects... #{spinner_chars[spinner_index]} (#{current}/#{total})"
|
|
1372
|
-
spinner_index = (spinner_index + 1) % spinner_chars.length
|
|
1373
|
-
end
|
|
1374
|
-
|
|
1375
|
-
print "\r Scanning projects... â (#{results.size} found)\n"
|
|
1376
|
-
puts ''
|
|
1377
|
-
|
|
1378
|
-
if results.empty?
|
|
1379
|
-
puts "â ī¸ No projects found in S3 for #{brand_key}"
|
|
1380
|
-
puts ' This may indicate:'
|
|
1381
|
-
puts ' - No files uploaded to S3 yet'
|
|
1382
|
-
puts ' - S3 bucket or prefix misconfigured'
|
|
1383
|
-
puts ' - AWS credentials issue'
|
|
1384
|
-
return
|
|
1385
|
-
end
|
|
1386
|
-
|
|
1387
|
-
# Load existing manifest
|
|
1388
|
-
brand_path = Appydave::Tools::Dam::Config.brand_path(brand_key)
|
|
1389
|
-
manifest_path = File.join(brand_path, 'projects.json')
|
|
1390
|
-
|
|
1391
|
-
unless File.exist?(manifest_path)
|
|
1392
|
-
puts "â Manifest not found: #{manifest_path}"
|
|
1393
|
-
puts " Run: dam manifest #{brand_key}"
|
|
1394
|
-
puts " Then retry: dam s3-scan #{brand_key}"
|
|
1395
|
-
exit 1
|
|
1396
|
-
end
|
|
1397
|
-
|
|
1398
|
-
manifest = JSON.parse(File.read(manifest_path), symbolize_names: true)
|
|
1399
|
-
|
|
1400
|
-
# Identify matched and orphaned S3 projects
|
|
1401
|
-
local_project_ids = manifest[:projects].map { |p| p[:id] }
|
|
1402
|
-
matched_projects = results.slice(*local_project_ids)
|
|
1403
|
-
orphaned_projects = results.reject { |project_id, _| local_project_ids.include?(project_id) }
|
|
1404
|
-
|
|
1405
|
-
# Merge S3 scan data into manifest for matched projects
|
|
1406
|
-
updated_count = 0
|
|
1407
|
-
manifest[:projects].each do |project|
|
|
1408
|
-
project_id = project[:id]
|
|
1409
|
-
s3_data = results[project_id]
|
|
1410
|
-
next unless s3_data
|
|
1411
|
-
|
|
1412
|
-
project[:storage][:s3] = s3_data
|
|
1413
|
-
updated_count += 1
|
|
1414
|
-
end
|
|
1415
|
-
|
|
1416
|
-
# Update timestamp and note
|
|
1417
|
-
manifest[:config][:last_updated] = Time.now.utc.iso8601
|
|
1418
|
-
manifest[:config][:note] = 'Auto-generated manifest with S3 scan data. Regenerate with: dam s3-scan'
|
|
1419
|
-
|
|
1420
|
-
# Write updated manifest
|
|
1421
|
-
File.write(manifest_path, JSON.pretty_generate(manifest))
|
|
1422
|
-
|
|
1423
|
-
# Add local sync status to matched projects
|
|
1424
|
-
Appydave::Tools::Dam::LocalSyncStatus.enrich!(matched_projects, brand_key)
|
|
1425
|
-
|
|
1426
|
-
# Display table
|
|
1427
|
-
display_s3_scan_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
1428
|
-
|
|
1429
|
-
# Summary
|
|
1430
|
-
total_manifest_projects = manifest[:projects].size
|
|
1431
|
-
missing_count = total_manifest_projects - matched_projects.size
|
|
1432
|
-
|
|
1433
|
-
puts ''
|
|
1434
|
-
puts 'âšī¸ Summary:'
|
|
1435
|
-
puts " âĸ Updated #{updated_count} projects in manifest"
|
|
1436
|
-
puts " âĸ #{missing_count} local project(s) not yet uploaded to S3" if missing_count.positive?
|
|
1437
|
-
puts " âĸ Manifest: #{manifest_path}"
|
|
1438
|
-
puts ''
|
|
1439
|
-
end
|
|
1440
|
-
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
1441
|
-
|
|
1442
|
-
# Display S3 scan results in table format
|
|
1443
|
-
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Style/FormatStringToken
|
|
1444
|
-
def display_s3_scan_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
1445
|
-
puts 'â
S3 Projects Report'
|
|
1446
|
-
puts ''
|
|
1447
|
-
puts 'PROJECT FILES SIZE LOCAL S3 MODIFIED'
|
|
1448
|
-
puts '-' * 92
|
|
1449
|
-
|
|
1450
|
-
# Display matched projects first (sorted alphabetically)
|
|
1451
|
-
matched_projects.sort.each do |project_id, data|
|
|
1452
|
-
files = data[:file_count].to_s.rjust(5)
|
|
1453
|
-
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
1454
|
-
local_status = Appydave::Tools::Dam::LocalSyncStatus.format(data[:local_status], data[:local_file_count], data[:file_count])
|
|
1455
|
-
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
1456
|
-
|
|
1457
|
-
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
1458
|
-
end
|
|
1459
|
-
|
|
1460
|
-
# Display orphaned projects (sorted alphabetically)
|
|
1461
|
-
return if orphaned_projects.empty?
|
|
1462
|
-
|
|
1463
|
-
puts '-' * 92
|
|
1464
|
-
orphaned_projects.sort.each do |project_id, data|
|
|
1465
|
-
files = data[:file_count].to_s.rjust(5)
|
|
1466
|
-
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
1467
|
-
local_status = 'N/A'
|
|
1468
|
-
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
1469
|
-
|
|
1470
|
-
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
1471
|
-
end
|
|
1472
|
-
|
|
1473
|
-
puts ''
|
|
1474
|
-
folder_word = orphaned_projects.size > 1 ? 'folders' : 'folder'
|
|
1475
|
-
puts "â ī¸ #{orphaned_projects.size} orphaned #{folder_word} found (no local project)"
|
|
1476
|
-
|
|
1477
|
-
orphaned_projects.sort.each do |project_id, _data|
|
|
1478
|
-
# Build AWS Console URL
|
|
1479
|
-
project_prefix = "#{prefix}#{project_id}/"
|
|
1480
|
-
console_url = "https://#{region}.console.aws.amazon.com/s3/buckets/#{bucket}?prefix=#{project_prefix}®ion=#{region}"
|
|
1481
|
-
puts " â #{project_id}"
|
|
1482
|
-
puts " #{console_url}"
|
|
1483
|
-
end
|
|
1484
|
-
end
|
|
1485
|
-
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Style/FormatStringToken
|
|
1486
|
-
|
|
1487
|
-
# rubocop:disable Metrics/MethodLength
|
|
1488
|
-
def scan_all_brands_s3
|
|
1489
|
-
Appydave::Tools::Configuration::Config.configure
|
|
1490
|
-
brands_config = Appydave::Tools::Configuration::Config.brands
|
|
1491
|
-
|
|
1492
|
-
results = []
|
|
1493
|
-
brands_config.brands.each do |brand_info|
|
|
1494
|
-
brand_key = brand_info.key
|
|
1495
|
-
puts ''
|
|
1496
|
-
puts '=' * 60
|
|
1497
|
-
|
|
1498
|
-
begin
|
|
1499
|
-
scan_single_brand_s3(brand_key)
|
|
1500
|
-
results << { brand: brand_key, success: true }
|
|
1501
|
-
rescue StandardError => e
|
|
1502
|
-
puts "â Failed to scan #{brand_key}: #{e.message}"
|
|
1503
|
-
results << { brand: brand_key, success: false, error: e.message }
|
|
1504
|
-
end
|
|
1505
|
-
end
|
|
1506
|
-
|
|
1507
|
-
puts ''
|
|
1508
|
-
puts '=' * 60
|
|
1509
|
-
puts 'đ Summary - S3 Scans:'
|
|
1510
|
-
puts ''
|
|
1511
|
-
|
|
1512
|
-
successful, failed = results.partition { |r| r[:success] }
|
|
1513
|
-
|
|
1514
|
-
successful.each do |result|
|
|
1515
|
-
brand_display = result[:brand].ljust(15)
|
|
1516
|
-
puts "â
#{brand_display} Scanned successfully"
|
|
1517
|
-
end
|
|
1518
|
-
|
|
1519
|
-
failed.each do |result|
|
|
1520
|
-
brand_display = result[:brand].ljust(15)
|
|
1521
|
-
puts "â #{brand_display} #{result[:error]}"
|
|
1522
|
-
end
|
|
1523
|
-
|
|
1524
|
-
puts ''
|
|
1525
|
-
puts "Total brands scanned: #{successful.size}/#{results.size}"
|
|
1526
|
-
end
|
|
1527
|
-
# rubocop:enable Metrics/MethodLength
|
|
1528
1346
|
end
|
|
1529
1347
|
|
|
1530
1348
|
# Run CLI
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
## Pending
|
|
11
11
|
- [x] extract-format-bytes â Replaced 4 callers (plan said 3; orphaned-projects loop in display_s3_scan_table was a 4th). format_bytes deleted. rubocop 0 offenses. Commit: 3cd362f.
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
12
|
+
- [x] extract-local-sync-status â LocalSyncStatus module created, 7 specs added (838 total), both methods gone from VatCLI. Side-fix: restored youtube_automation_config require incorrectly removed in prior commit. v0.76.5.
|
|
13
|
+
- [~] extract-s3-scan-command â Extract `scan_single_brand_s3` + `scan_all_brands_s3` + `display_s3_scan_table` â new `S3ScanCommand` class; add spec; **depends on extract-local-sync-status completing first**
|
|
14
14
|
- [ ] extract-s3-arg-parser â Extract `parse_s3_args` + `valid_brand?` + `parse_share_args` + `show_share_usage_and_exit` + `parse_discover_args` â new `S3ArgParser` class; add spec
|
|
15
15
|
|
|
16
16
|
## In Progress
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appydave
|
|
4
|
+
module Tools
|
|
5
|
+
module Dam
|
|
6
|
+
# Encapsulates S3 scan logic: single-brand and all-brands scanning
|
|
7
|
+
class S3ScanCommand
|
|
8
|
+
# Scan a single brand's S3 bucket and update its manifest
|
|
9
|
+
def scan_single(brand_key)
|
|
10
|
+
puts "đ Scanning S3 for #{brand_key}..."
|
|
11
|
+
puts ''
|
|
12
|
+
|
|
13
|
+
scanner = Appydave::Tools::Dam::S3Scanner.new(brand_key)
|
|
14
|
+
|
|
15
|
+
# Get brand info for S3 path
|
|
16
|
+
Appydave::Tools::Configuration::Config.configure
|
|
17
|
+
brand_info = Appydave::Tools::Configuration::Config.brands.get_brand(brand_key)
|
|
18
|
+
bucket = brand_info.aws.s3_bucket
|
|
19
|
+
prefix = brand_info.aws.s3_prefix
|
|
20
|
+
region = brand_info.aws.region
|
|
21
|
+
|
|
22
|
+
# Spinner characters for progress
|
|
23
|
+
spinner_chars = ['â ', 'â ', 'â š', 'â ¸', 'â ŧ', 'â ´', 'â Ļ', 'â §', 'â ', 'â ']
|
|
24
|
+
spinner_index = 0
|
|
25
|
+
|
|
26
|
+
print "đ Scanning s3://#{bucket}/#{prefix}\n"
|
|
27
|
+
print ' Scanning projects... '
|
|
28
|
+
|
|
29
|
+
# Scan all projects with progress callback
|
|
30
|
+
results = scanner.scan_all_projects(show_progress: false) do |current, total|
|
|
31
|
+
print "\r Scanning projects... #{spinner_chars[spinner_index]} (#{current}/#{total})"
|
|
32
|
+
spinner_index = (spinner_index + 1) % spinner_chars.length
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
print "\r Scanning projects... â (#{results.size} found)\n"
|
|
36
|
+
puts ''
|
|
37
|
+
|
|
38
|
+
if results.empty?
|
|
39
|
+
puts "â ī¸ No projects found in S3 for #{brand_key}"
|
|
40
|
+
puts ' This may indicate:'
|
|
41
|
+
puts ' - No files uploaded to S3 yet'
|
|
42
|
+
puts ' - S3 bucket or prefix misconfigured'
|
|
43
|
+
puts ' - AWS credentials issue'
|
|
44
|
+
return
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Load existing manifest
|
|
48
|
+
brand_path = Appydave::Tools::Dam::Config.brand_path(brand_key)
|
|
49
|
+
manifest_path = File.join(brand_path, 'projects.json')
|
|
50
|
+
|
|
51
|
+
unless File.exist?(manifest_path)
|
|
52
|
+
puts "â Manifest not found: #{manifest_path}"
|
|
53
|
+
puts " Run: dam manifest #{brand_key}"
|
|
54
|
+
puts " Then retry: dam s3-scan #{brand_key}"
|
|
55
|
+
exit 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
manifest = JSON.parse(File.read(manifest_path), symbolize_names: true)
|
|
59
|
+
|
|
60
|
+
# Identify matched and orphaned S3 projects
|
|
61
|
+
local_project_ids = manifest[:projects].map { |p| p[:id] }
|
|
62
|
+
matched_projects = results.slice(*local_project_ids)
|
|
63
|
+
orphaned_projects = results.reject { |project_id, _| local_project_ids.include?(project_id) }
|
|
64
|
+
|
|
65
|
+
# Merge S3 scan data into manifest for matched projects
|
|
66
|
+
updated_count = 0
|
|
67
|
+
manifest[:projects].each do |project|
|
|
68
|
+
project_id = project[:id]
|
|
69
|
+
s3_data = results[project_id]
|
|
70
|
+
next unless s3_data
|
|
71
|
+
|
|
72
|
+
project[:storage][:s3] = s3_data
|
|
73
|
+
updated_count += 1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Update timestamp and note
|
|
77
|
+
manifest[:config][:last_updated] = Time.now.utc.iso8601
|
|
78
|
+
manifest[:config][:note] = 'Auto-generated manifest with S3 scan data. Regenerate with: dam s3-scan'
|
|
79
|
+
|
|
80
|
+
# Write updated manifest
|
|
81
|
+
File.write(manifest_path, JSON.pretty_generate(manifest))
|
|
82
|
+
|
|
83
|
+
# Add local sync status to matched projects
|
|
84
|
+
Appydave::Tools::Dam::LocalSyncStatus.enrich!(matched_projects, brand_key)
|
|
85
|
+
|
|
86
|
+
# Display table
|
|
87
|
+
display_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
88
|
+
|
|
89
|
+
# Summary
|
|
90
|
+
total_manifest_projects = manifest[:projects].size
|
|
91
|
+
missing_count = total_manifest_projects - matched_projects.size
|
|
92
|
+
|
|
93
|
+
puts ''
|
|
94
|
+
puts 'âšī¸ Summary:'
|
|
95
|
+
puts " âĸ Updated #{updated_count} projects in manifest"
|
|
96
|
+
puts " âĸ #{missing_count} local project(s) not yet uploaded to S3" if missing_count.positive?
|
|
97
|
+
puts " âĸ Manifest: #{manifest_path}"
|
|
98
|
+
puts ''
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Scan all brands' S3 buckets
|
|
102
|
+
def scan_all
|
|
103
|
+
Appydave::Tools::Configuration::Config.configure
|
|
104
|
+
brands_config = Appydave::Tools::Configuration::Config.brands
|
|
105
|
+
|
|
106
|
+
results = []
|
|
107
|
+
brands_config.brands.each do |brand_info|
|
|
108
|
+
brand_key = brand_info.key
|
|
109
|
+
puts ''
|
|
110
|
+
puts '=' * 60
|
|
111
|
+
|
|
112
|
+
begin
|
|
113
|
+
scan_single(brand_key)
|
|
114
|
+
results << { brand: brand_key, success: true }
|
|
115
|
+
rescue StandardError => e
|
|
116
|
+
puts "â Failed to scan #{brand_key}: #{e.message}"
|
|
117
|
+
results << { brand: brand_key, success: false, error: e.message }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
puts ''
|
|
122
|
+
puts '=' * 60
|
|
123
|
+
puts 'đ Summary - S3 Scans:'
|
|
124
|
+
puts ''
|
|
125
|
+
|
|
126
|
+
successful, failed = results.partition { |r| r[:success] }
|
|
127
|
+
|
|
128
|
+
successful.each do |result|
|
|
129
|
+
brand_display = result[:brand].ljust(15)
|
|
130
|
+
puts "â
#{brand_display} Scanned successfully"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
failed.each do |result|
|
|
134
|
+
brand_display = result[:brand].ljust(15)
|
|
135
|
+
puts "â #{brand_display} #{result[:error]}"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
puts ''
|
|
139
|
+
puts "Total brands scanned: #{successful.size}/#{results.size}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
private
|
|
143
|
+
|
|
144
|
+
# Display S3 scan results in table format
|
|
145
|
+
# rubocop:disable Style/FormatStringToken
|
|
146
|
+
def display_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
147
|
+
puts 'â
S3 Projects Report'
|
|
148
|
+
puts ''
|
|
149
|
+
puts 'PROJECT FILES SIZE LOCAL S3 MODIFIED'
|
|
150
|
+
puts '-' * 92
|
|
151
|
+
|
|
152
|
+
# Display matched projects first (sorted alphabetically)
|
|
153
|
+
matched_projects.sort.each do |project_id, data|
|
|
154
|
+
files = data[:file_count].to_s.rjust(5)
|
|
155
|
+
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
156
|
+
local_status = Appydave::Tools::Dam::LocalSyncStatus.format(data[:local_status], data[:local_file_count], data[:file_count])
|
|
157
|
+
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
158
|
+
|
|
159
|
+
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Display orphaned projects (sorted alphabetically)
|
|
163
|
+
return if orphaned_projects.empty?
|
|
164
|
+
|
|
165
|
+
puts '-' * 92
|
|
166
|
+
orphaned_projects.sort.each do |project_id, data|
|
|
167
|
+
files = data[:file_count].to_s.rjust(5)
|
|
168
|
+
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
169
|
+
local_status = 'N/A'
|
|
170
|
+
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
171
|
+
|
|
172
|
+
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
puts ''
|
|
176
|
+
folder_word = orphaned_projects.size > 1 ? 'folders' : 'folder'
|
|
177
|
+
puts "â ī¸ #{orphaned_projects.size} orphaned #{folder_word} found (no local project)"
|
|
178
|
+
|
|
179
|
+
orphaned_projects.sort.each do |project_id, _data|
|
|
180
|
+
# Build AWS Console URL
|
|
181
|
+
project_prefix = "#{prefix}#{project_id}/"
|
|
182
|
+
console_url = "https://#{region}.console.aws.amazon.com/s3/buckets/#{bucket}?prefix=#{project_prefix}®ion=#{region}"
|
|
183
|
+
puts " â #{project_id}"
|
|
184
|
+
puts " #{console_url}"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
# rubocop:enable Style/FormatStringToken
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
data/lib/appydave/tools.rb
CHANGED
|
@@ -79,6 +79,7 @@ require 'appydave/tools/dam/repo_status'
|
|
|
79
79
|
require 'appydave/tools/dam/repo_sync'
|
|
80
80
|
require 'appydave/tools/dam/repo_push'
|
|
81
81
|
require 'appydave/tools/dam/local_sync_status'
|
|
82
|
+
require 'appydave/tools/dam/s3_scan_command'
|
|
82
83
|
|
|
83
84
|
require 'appydave/tools/jump/path_validator'
|
|
84
85
|
require 'appydave/tools/jump/location'
|
data/package.json
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appydave-tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.76.
|
|
4
|
+
version: 0.76.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cruwys
|
|
@@ -362,6 +362,7 @@ files:
|
|
|
362
362
|
- lib/appydave/tools/dam/repo_status.rb
|
|
363
363
|
- lib/appydave/tools/dam/repo_sync.rb
|
|
364
364
|
- lib/appydave/tools/dam/s3_operations.rb
|
|
365
|
+
- lib/appydave/tools/dam/s3_scan_command.rb
|
|
365
366
|
- lib/appydave/tools/dam/s3_scanner.rb
|
|
366
367
|
- lib/appydave/tools/dam/share_operations.rb
|
|
367
368
|
- lib/appydave/tools/dam/ssd_status.rb
|