bard-api 0.1.0 → 0.3.1
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/README.md +9 -2
- data/lib/bard/api/app.rb +12 -28
- data/lib/bard/api/version.rb +1 -1
- data/lib/bard/api.rb +0 -2
- data/lib/bard-api.rb +1 -0
- metadata +43 -26
- data/lib/bard/api/backup.rb +0 -95
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 70f38ef8f674aefa2cdcfba3586e87d644c10026943625bd82cb2be180f0035b
|
|
4
|
+
data.tar.gz: 1fd66c7e938efe753797d99e594c03f802948c004adafe0991b2b5577a00fb73
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6ce89073234248cf2a6ec1cc628bb97fcbf8f8d96e8be9d46dd117f54b1f18277e4c81cd9ec3ba2fb7fbd6fc1ef53bed84532f603db84ffda376cbd87b08f28e
|
|
7
|
+
data.tar.gz: 1119c0bc33153aeb74d53ec585c59b7bade8c410eda343962e9c2d5cf04bb017e8d2cb7e441c31c89c1dd4b687dcccc0ed1121e5fc7de2d8fbe158ce7ac34e8e
|
data/README.md
CHANGED
|
@@ -80,17 +80,24 @@ Authorization: Bearer <jwt-token>
|
|
|
80
80
|
```json
|
|
81
81
|
{
|
|
82
82
|
"timestamp": "2025-12-06T10:30:00Z",
|
|
83
|
-
"size": 123456789,
|
|
84
83
|
"destinations": [
|
|
85
84
|
{
|
|
86
85
|
"name": "primary",
|
|
87
86
|
"type": "s3",
|
|
88
|
-
"
|
|
87
|
+
"path": "bard-backup/my-app",
|
|
88
|
+
"region": "us-west-2"
|
|
89
89
|
}
|
|
90
90
|
]
|
|
91
91
|
}
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
**Response (404 Not Found):**
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"error": "No backups found"
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
94
101
|
### Authentication
|
|
95
102
|
|
|
96
103
|
The API uses JWT with asymmetric RSA keys for authentication. The public key is embedded in the gem, and only BARD Tracker with the private key can create valid tokens.
|
data/lib/bard/api/app.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "rack"
|
|
4
4
|
require "json"
|
|
5
5
|
require_relative "auth"
|
|
6
|
-
|
|
6
|
+
require "bard/backup"
|
|
7
7
|
|
|
8
8
|
module Bard
|
|
9
9
|
module Api
|
|
@@ -24,7 +24,7 @@ module Bard
|
|
|
24
24
|
not_found
|
|
25
25
|
end
|
|
26
26
|
rescue => e
|
|
27
|
-
|
|
27
|
+
json_response(500, { error: e.message })
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
private
|
|
@@ -35,34 +35,22 @@ module Bard
|
|
|
35
35
|
|
|
36
36
|
def create_backup(request)
|
|
37
37
|
with_auth(request) do |payload|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
backup
|
|
44
|
-
result = backup.perform(urls)
|
|
45
|
-
|
|
46
|
-
json_response(200, result)
|
|
38
|
+
backup = Bard::Backup.create!({
|
|
39
|
+
name: "bard",
|
|
40
|
+
type: :upload,
|
|
41
|
+
urls: payload["urls"]
|
|
42
|
+
})
|
|
43
|
+
json_response(200, backup.as_json)
|
|
47
44
|
end
|
|
48
|
-
rescue => e
|
|
49
|
-
json_response(500, { error: "Backup failed: #{e.message}" })
|
|
50
45
|
end
|
|
51
46
|
|
|
52
47
|
def latest_backup(request)
|
|
53
48
|
with_auth(request) do
|
|
54
|
-
|
|
55
|
-
backup
|
|
56
|
-
result = backup.latest
|
|
57
|
-
|
|
58
|
-
if result
|
|
59
|
-
json_response(200, result)
|
|
60
|
-
else
|
|
61
|
-
json_response(404, { error: "No backups found" })
|
|
62
|
-
end
|
|
49
|
+
backup = Bard::Backup.latest
|
|
50
|
+
json_response(200, backup.as_json)
|
|
63
51
|
end
|
|
64
|
-
rescue => e
|
|
65
|
-
json_response(
|
|
52
|
+
rescue Bard::Backup::NotFound => e
|
|
53
|
+
json_response(404, { error: e.message })
|
|
66
54
|
end
|
|
67
55
|
|
|
68
56
|
def with_auth(request)
|
|
@@ -79,10 +67,6 @@ module Bard
|
|
|
79
67
|
def not_found
|
|
80
68
|
json_response(404, { error: "Not found" })
|
|
81
69
|
end
|
|
82
|
-
|
|
83
|
-
def internal_error(e)
|
|
84
|
-
json_response(500, { error: "Internal server error: #{e.message}" })
|
|
85
|
-
end
|
|
86
70
|
end
|
|
87
71
|
end
|
|
88
72
|
end
|
data/lib/bard/api/version.rb
CHANGED
data/lib/bard/api.rb
CHANGED
data/lib/bard-api.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bard/api"
|
metadata
CHANGED
|
@@ -1,84 +1,99 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bard-api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Micah Geisel
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date: 2025-12-
|
|
11
|
+
date: 2025-12-11 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: jwt
|
|
14
15
|
requirement: !ruby/object:Gem::Requirement
|
|
15
16
|
requirements:
|
|
16
|
-
- - "
|
|
17
|
+
- - ">="
|
|
17
18
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
19
|
+
version: '0'
|
|
19
20
|
type: :runtime
|
|
20
21
|
prerelease: false
|
|
21
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
23
|
requirements:
|
|
23
|
-
- - "
|
|
24
|
+
- - ">="
|
|
24
25
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '
|
|
26
|
+
version: '0'
|
|
26
27
|
- !ruby/object:Gem::Dependency
|
|
27
28
|
name: rack
|
|
28
29
|
requirement: !ruby/object:Gem::Requirement
|
|
29
30
|
requirements:
|
|
30
|
-
- - "
|
|
31
|
+
- - ">="
|
|
31
32
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
33
|
+
version: '0'
|
|
33
34
|
type: :runtime
|
|
34
35
|
prerelease: false
|
|
35
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
37
|
requirements:
|
|
37
|
-
- - "
|
|
38
|
+
- - ">="
|
|
38
39
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
40
|
+
version: '0'
|
|
40
41
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name:
|
|
42
|
+
name: backhoe
|
|
42
43
|
requirement: !ruby/object:Gem::Requirement
|
|
43
44
|
requirements:
|
|
44
|
-
- - "
|
|
45
|
+
- - ">="
|
|
45
46
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
47
|
+
version: '0'
|
|
47
48
|
type: :runtime
|
|
48
49
|
prerelease: false
|
|
49
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
51
|
requirements:
|
|
51
|
-
- - "
|
|
52
|
+
- - ">="
|
|
52
53
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
54
|
+
version: '0'
|
|
54
55
|
- !ruby/object:Gem::Dependency
|
|
55
|
-
name:
|
|
56
|
+
name: bard
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: bard-backup
|
|
56
71
|
requirement: !ruby/object:Gem::Requirement
|
|
57
72
|
requirements:
|
|
58
|
-
- - "
|
|
73
|
+
- - ">="
|
|
59
74
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '0
|
|
75
|
+
version: '0'
|
|
61
76
|
type: :runtime
|
|
62
77
|
prerelease: false
|
|
63
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
79
|
requirements:
|
|
65
|
-
- - "
|
|
80
|
+
- - ">="
|
|
66
81
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '0
|
|
82
|
+
version: '0'
|
|
68
83
|
- !ruby/object:Gem::Dependency
|
|
69
84
|
name: rack-test
|
|
70
85
|
requirement: !ruby/object:Gem::Requirement
|
|
71
86
|
requirements:
|
|
72
|
-
- - "
|
|
87
|
+
- - ">="
|
|
73
88
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: '
|
|
89
|
+
version: '0'
|
|
75
90
|
type: :development
|
|
76
91
|
prerelease: false
|
|
77
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
93
|
requirements:
|
|
79
|
-
- - "
|
|
94
|
+
- - ">="
|
|
80
95
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: '
|
|
96
|
+
version: '0'
|
|
82
97
|
description: Rack app that mounts in Rails projects to expose management endpoints
|
|
83
98
|
for BARD Tracker
|
|
84
99
|
email:
|
|
@@ -92,10 +107,10 @@ files:
|
|
|
92
107
|
- README.md
|
|
93
108
|
- Rakefile
|
|
94
109
|
- config.ru
|
|
110
|
+
- lib/bard-api.rb
|
|
95
111
|
- lib/bard/api.rb
|
|
96
112
|
- lib/bard/api/app.rb
|
|
97
113
|
- lib/bard/api/auth.rb
|
|
98
|
-
- lib/bard/api/backup.rb
|
|
99
114
|
- lib/bard/api/version.rb
|
|
100
115
|
homepage: https://github.com/botandrose/bard-api
|
|
101
116
|
licenses:
|
|
@@ -103,6 +118,7 @@ licenses:
|
|
|
103
118
|
metadata:
|
|
104
119
|
homepage_uri: https://github.com/botandrose/bard-api
|
|
105
120
|
source_code_uri: https://github.com/botandrose/bard-api
|
|
121
|
+
post_install_message:
|
|
106
122
|
rdoc_options: []
|
|
107
123
|
require_paths:
|
|
108
124
|
- lib
|
|
@@ -117,7 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
117
133
|
- !ruby/object:Gem::Version
|
|
118
134
|
version: '0'
|
|
119
135
|
requirements: []
|
|
120
|
-
rubygems_version: 3.
|
|
136
|
+
rubygems_version: 3.5.11
|
|
137
|
+
signing_key:
|
|
121
138
|
specification_version: 4
|
|
122
139
|
summary: REST API for BARD-managed Rails projects
|
|
123
140
|
test_files: []
|
data/lib/bard/api/backup.rb
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "backhoe"
|
|
4
|
-
require "http"
|
|
5
|
-
require "time"
|
|
6
|
-
require "fileutils"
|
|
7
|
-
|
|
8
|
-
module Bard
|
|
9
|
-
module Api
|
|
10
|
-
class Backup
|
|
11
|
-
class BackupError < StandardError; end
|
|
12
|
-
|
|
13
|
-
# Perform a backup to the specified URLs
|
|
14
|
-
def perform(urls)
|
|
15
|
-
raise BackupError, "No URLs provided" if urls.nil? || urls.empty?
|
|
16
|
-
|
|
17
|
-
timestamp = Time.now.utc
|
|
18
|
-
destinations = []
|
|
19
|
-
errors = []
|
|
20
|
-
|
|
21
|
-
# Create temp file with timestamp
|
|
22
|
-
filename = "#{timestamp.iso8601}.sql.gz"
|
|
23
|
-
temp_path = "/tmp/#{filename}"
|
|
24
|
-
|
|
25
|
-
begin
|
|
26
|
-
# Dump database to temp file using Backhoe
|
|
27
|
-
Backhoe.dump(temp_path)
|
|
28
|
-
|
|
29
|
-
# Get file size
|
|
30
|
-
file_size = File.size(temp_path)
|
|
31
|
-
|
|
32
|
-
# Upload to all URLs in parallel
|
|
33
|
-
threads = urls.map do |url|
|
|
34
|
-
Thread.new do
|
|
35
|
-
begin
|
|
36
|
-
upload_to_url(url, temp_path)
|
|
37
|
-
{
|
|
38
|
-
name: "bard",
|
|
39
|
-
type: "bard",
|
|
40
|
-
status: "success"
|
|
41
|
-
}
|
|
42
|
-
rescue => e
|
|
43
|
-
errors << e
|
|
44
|
-
{
|
|
45
|
-
name: "bard",
|
|
46
|
-
type: "bard",
|
|
47
|
-
status: "failed",
|
|
48
|
-
error: e.message
|
|
49
|
-
}
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Wait for all uploads to complete
|
|
55
|
-
destinations = threads.map(&:value)
|
|
56
|
-
ensure
|
|
57
|
-
# Clean up temp file
|
|
58
|
-
FileUtils.rm_f(temp_path)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Store backup metadata
|
|
62
|
-
@last_backup = {
|
|
63
|
-
timestamp: timestamp.iso8601,
|
|
64
|
-
size: file_size,
|
|
65
|
-
destinations: destinations
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
# Raise error if any destination failed
|
|
69
|
-
unless errors.empty?
|
|
70
|
-
raise BackupError, "Some destinations failed: #{errors.map(&:message).join(", ")}"
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
@last_backup
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Get the latest backup status
|
|
77
|
-
def latest
|
|
78
|
-
# TODO: Retrieve from database instead of instance variable
|
|
79
|
-
@last_backup
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
private
|
|
83
|
-
|
|
84
|
-
def upload_to_url(url, file_path)
|
|
85
|
-
File.open(file_path, "rb") do |file|
|
|
86
|
-
response = HTTP.put(url, body: file)
|
|
87
|
-
|
|
88
|
-
unless response.status.success?
|
|
89
|
-
raise BackupError, "Upload failed with status #{response.status}: #{response.body}"
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|