etna 0.1.14 → 0.1.20
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/bin/etna +18 -0
- data/etna.completion +1001 -0
- data/etna_app.completion +133 -0
- data/ext/completions/extconf.rb +20 -0
- data/lib/commands.rb +395 -0
- data/lib/etna.rb +7 -0
- data/lib/etna/application.rb +46 -22
- data/lib/etna/client.rb +82 -48
- data/lib/etna/clients.rb +4 -0
- data/lib/etna/clients/enum.rb +9 -0
- data/lib/etna/clients/janus.rb +2 -0
- data/lib/etna/clients/janus/client.rb +73 -0
- data/lib/etna/clients/janus/models.rb +78 -0
- data/lib/etna/clients/magma.rb +4 -0
- data/lib/etna/clients/magma/client.rb +80 -0
- data/lib/etna/clients/magma/formatting.rb +1 -0
- data/lib/etna/clients/magma/formatting/models_csv.rb +354 -0
- data/lib/etna/clients/magma/models.rb +630 -0
- data/lib/etna/clients/magma/workflows.rb +10 -0
- data/lib/etna/clients/magma/workflows/add_project_models_workflow.rb +67 -0
- data/lib/etna/clients/magma/workflows/attribute_actions_from_json_workflow.rb +62 -0
- data/lib/etna/clients/magma/workflows/create_project_workflow.rb +123 -0
- data/lib/etna/clients/magma/workflows/crud_workflow.rb +85 -0
- data/lib/etna/clients/magma/workflows/ensure_containing_record_workflow.rb +44 -0
- data/lib/etna/clients/magma/workflows/file_attributes_blank_workflow.rb +68 -0
- data/lib/etna/clients/magma/workflows/file_linking_workflow.rb +115 -0
- data/lib/etna/clients/magma/workflows/json_converters.rb +81 -0
- data/lib/etna/clients/magma/workflows/json_validators.rb +452 -0
- data/lib/etna/clients/magma/workflows/model_synchronization_workflow.rb +306 -0
- data/lib/etna/clients/magma/workflows/record_synchronization_workflow.rb +63 -0
- data/lib/etna/clients/magma/workflows/update_attributes_from_csv_workflow.rb +246 -0
- data/lib/etna/clients/metis.rb +3 -0
- data/lib/etna/clients/metis/client.rb +239 -0
- data/lib/etna/clients/metis/models.rb +313 -0
- data/lib/etna/clients/metis/workflows.rb +2 -0
- data/lib/etna/clients/metis/workflows/metis_download_workflow.rb +37 -0
- data/lib/etna/clients/metis/workflows/metis_upload_workflow.rb +137 -0
- data/lib/etna/clients/polyphemus.rb +3 -0
- data/lib/etna/clients/polyphemus/client.rb +33 -0
- data/lib/etna/clients/polyphemus/models.rb +68 -0
- data/lib/etna/clients/polyphemus/workflows.rb +1 -0
- data/lib/etna/clients/polyphemus/workflows/set_configuration_workflow.rb +47 -0
- data/lib/etna/command.rb +243 -5
- data/lib/etna/controller.rb +4 -0
- data/lib/etna/csvs.rb +159 -0
- data/lib/etna/directed_graph.rb +56 -0
- data/lib/etna/environment_scoped.rb +19 -0
- data/lib/etna/errors.rb +6 -0
- data/lib/etna/generate_autocompletion_script.rb +131 -0
- data/lib/etna/json_serializable_struct.rb +37 -0
- data/lib/etna/logger.rb +24 -2
- data/lib/etna/multipart_serializable_nested_hash.rb +50 -0
- data/lib/etna/route.rb +1 -1
- data/lib/etna/server.rb +3 -0
- data/lib/etna/spec/vcr.rb +99 -0
- data/lib/etna/templates/attribute_actions_template.json +43 -0
- data/lib/etna/test_auth.rb +3 -1
- data/lib/etna/user.rb +11 -1
- data/lib/helpers.rb +90 -0
- metadata +70 -5
@@ -0,0 +1,239 @@
|
|
1
|
+
require 'net/http/persistent'
|
2
|
+
require 'net/http/post/multipart'
|
3
|
+
require 'singleton'
|
4
|
+
require 'cgi'
|
5
|
+
require 'json'
|
6
|
+
require_relative '../../client'
|
7
|
+
require_relative './models'
|
8
|
+
|
9
|
+
module Etna
|
10
|
+
module Clients
|
11
|
+
class Metis
|
12
|
+
attr_reader :token
|
13
|
+
def initialize(host:, token:, persistent: true, ignore_ssl: false)
|
14
|
+
raise 'Metis client configuration is missing host.' unless host
|
15
|
+
raise 'Metis client configuration is missing token.' unless token
|
16
|
+
@etna_client = ::Etna::Client.new(
|
17
|
+
host,
|
18
|
+
token,
|
19
|
+
persistent: persistent,
|
20
|
+
ignore_ssl: ignore_ssl)
|
21
|
+
|
22
|
+
@token = token
|
23
|
+
end
|
24
|
+
|
25
|
+
def list_all_folders(list_all_folders_request = ListFoldersRequest.new)
|
26
|
+
FoldersResponse.new(
|
27
|
+
@etna_client.folder_list_all_folders(list_all_folders_request.to_h))
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_folder(list_folder_request = ListFolderRequest.new)
|
31
|
+
FoldersAndFilesResponse.new(
|
32
|
+
@etna_client.folder_list(list_folder_request.to_h))
|
33
|
+
end
|
34
|
+
|
35
|
+
def ensure_parent_folder_exists(project_name:, bucket_name:, path:)
|
36
|
+
create_folder_request = CreateFolderRequest.new(
|
37
|
+
project_name: project_name,
|
38
|
+
bucket_name: bucket_name,
|
39
|
+
folder_path: parent_folder_path(path)
|
40
|
+
)
|
41
|
+
create_folder(create_folder_request) if !folder_exists?(create_folder_request)
|
42
|
+
end
|
43
|
+
|
44
|
+
def rename_folder(rename_folder_request)
|
45
|
+
ensure_parent_folder_exists(
|
46
|
+
project_name: rename_folder_request.project_name,
|
47
|
+
bucket_name: rename_folder_request.new_bucket_name,
|
48
|
+
path: rename_folder_request.new_folder_path
|
49
|
+
) if rename_folder_request.create_parent
|
50
|
+
|
51
|
+
FoldersResponse.new(
|
52
|
+
@etna_client.folder_rename(rename_folder_request.to_h))
|
53
|
+
end
|
54
|
+
|
55
|
+
def rename_file(rename_file_request)
|
56
|
+
ensure_parent_folder_exists(
|
57
|
+
project_name: rename_file_request.project_name,
|
58
|
+
bucket_name: rename_file_request.new_bucket_name,
|
59
|
+
path: rename_file_request.new_file_path # ensure_parent_folder_exists() parses this for the parent path
|
60
|
+
) if rename_file_request.create_parent
|
61
|
+
|
62
|
+
FilesResponse.new(
|
63
|
+
@etna_client.file_rename(rename_file_request.to_h))
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_folder(create_folder_request)
|
67
|
+
FoldersResponse.new(
|
68
|
+
@etna_client.folder_create(create_folder_request.to_h))
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete_folder(delete_folder_request)
|
72
|
+
FoldersResponse.new(
|
73
|
+
@etna_client.folder_remove(delete_folder_request.to_h))
|
74
|
+
end
|
75
|
+
|
76
|
+
def find(find_request)
|
77
|
+
FoldersAndFilesResponse.new(
|
78
|
+
@etna_client.bucket_find(find_request.to_h))
|
79
|
+
end
|
80
|
+
|
81
|
+
def download_file(file_or_url = File.new, &block)
|
82
|
+
if file_or_url.instance_of?(File)
|
83
|
+
download_path = file_or_url.download_path
|
84
|
+
else
|
85
|
+
download_path = file_or_url.sub(%r!^https://[^/]*?/!, '/')
|
86
|
+
end
|
87
|
+
|
88
|
+
@etna_client.get(download_path) do |response|
|
89
|
+
response.read_body(&block)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def upload_start(upload_start_request = UploadStartRequest.new)
|
94
|
+
json = nil
|
95
|
+
@etna_client.post(upload_start_request.upload_path, upload_start_request) do |res|
|
96
|
+
json = JSON.parse(res.body)
|
97
|
+
end
|
98
|
+
|
99
|
+
UploadResponse.new(json)
|
100
|
+
end
|
101
|
+
|
102
|
+
def authorize_upload(authorize_upload_request = AuthorizeUploadRequest.new)
|
103
|
+
json = nil
|
104
|
+
@etna_client.post("/authorize/upload", authorize_upload_request) do |res|
|
105
|
+
json = JSON.parse(res.body)
|
106
|
+
end
|
107
|
+
|
108
|
+
UploadResponse.new(json)
|
109
|
+
end
|
110
|
+
|
111
|
+
def upload_blob(upload_blob_request = UploadBlobRequest.new)
|
112
|
+
json = nil
|
113
|
+
@etna_client.multipart_post(upload_blob_request.upload_path, upload_blob_request.encode_multipart_content) do |res|
|
114
|
+
json = JSON.parse(res.body)
|
115
|
+
end
|
116
|
+
|
117
|
+
UploadResponse.new(json)
|
118
|
+
end
|
119
|
+
|
120
|
+
def copy_files(copy_files_request)
|
121
|
+
FilesResponse.new(
|
122
|
+
@etna_client.file_bulk_copy(copy_files_request.to_h))
|
123
|
+
end
|
124
|
+
|
125
|
+
def folder_exists?(create_folder_request)
|
126
|
+
# NOTE: this doesn't test if the folder_path itself exists
|
127
|
+
# This can be confusing for root folders, because
|
128
|
+
# they have no parents, so you don't need
|
129
|
+
# to create anything.
|
130
|
+
return true if create_folder_request.folder_path.empty? # root folder
|
131
|
+
|
132
|
+
# returns 422 if the folder_path does not exist
|
133
|
+
begin
|
134
|
+
list_folder(
|
135
|
+
Etna::Clients::Metis::ListFolderRequest.new(
|
136
|
+
project_name: create_folder_request.project_name,
|
137
|
+
bucket_name: create_folder_request.bucket_name,
|
138
|
+
folder_path: create_folder_request.folder_path
|
139
|
+
))
|
140
|
+
rescue Etna::Error => e
|
141
|
+
return false if e.status == 422
|
142
|
+
raise
|
143
|
+
end
|
144
|
+
return true
|
145
|
+
end
|
146
|
+
|
147
|
+
def folders(project_name:, bucket_name:)
|
148
|
+
@folders ||= Hash.new { |h, key|
|
149
|
+
h[key] = list_all_folders(
|
150
|
+
Etna::Clients::Metis::ListFoldersRequest.new(
|
151
|
+
project_name: project_name,
|
152
|
+
bucket_name: key
|
153
|
+
)).folders.all
|
154
|
+
}
|
155
|
+
|
156
|
+
@folders[bucket_name]
|
157
|
+
end
|
158
|
+
|
159
|
+
def rename_folders_by_regex(project_name:, source_bucket:, source_folders:, dest_bucket:, regex:)
|
160
|
+
found_folders = source_folders.select { |folder|
|
161
|
+
folder.folder_path =~ regex
|
162
|
+
}
|
163
|
+
|
164
|
+
return if found_folders.length == 0
|
165
|
+
|
166
|
+
found_folders.each { |folder|
|
167
|
+
# If the destination folder already exists, we need to copy the files
|
168
|
+
# over to it and delete the source folder.
|
169
|
+
create_folder_request = CreateFolderRequest.new(
|
170
|
+
project_name: project_name,
|
171
|
+
bucket_name: dest_bucket,
|
172
|
+
folder_path: folder.folder_path
|
173
|
+
)
|
174
|
+
|
175
|
+
if folder_exists?(create_folder_request)
|
176
|
+
recursively_rename_folder(
|
177
|
+
project_name: project_name,
|
178
|
+
source_bucket: source_bucket,
|
179
|
+
dest_bucket: dest_bucket,
|
180
|
+
folder: folder
|
181
|
+
)
|
182
|
+
else
|
183
|
+
rename_folder(Etna::Clients::Metis::RenameFolderRequest.new(
|
184
|
+
bucket_name: source_bucket,
|
185
|
+
project_name: project_name,
|
186
|
+
folder_path: folder.folder_path,
|
187
|
+
new_bucket_name: dest_bucket,
|
188
|
+
new_folder_path: folder.folder_path,
|
189
|
+
create_parent: true)
|
190
|
+
)
|
191
|
+
end
|
192
|
+
}
|
193
|
+
end
|
194
|
+
|
195
|
+
def recursively_rename_folder(project_name:, source_bucket:, dest_bucket:, folder:)
|
196
|
+
folder_contents = list_folder(
|
197
|
+
Etna::Clients::Metis::ListFolderRequest.new(
|
198
|
+
project_name: project_name,
|
199
|
+
bucket_name: source_bucket,
|
200
|
+
folder_path: folder.folder_path
|
201
|
+
))
|
202
|
+
|
203
|
+
folder_contents.folders.all.each do |sub_folder|
|
204
|
+
recursively_rename_folder(
|
205
|
+
project_name: project_name,
|
206
|
+
source_bucket: source_bucket,
|
207
|
+
dest_bucket: dest_bucket,
|
208
|
+
folder: sub_folder
|
209
|
+
)
|
210
|
+
end
|
211
|
+
|
212
|
+
folder_contents.files.all.each do |file|
|
213
|
+
rename_file(Etna::Clients::Metis::RenameFileRequest.new(
|
214
|
+
bucket_name: source_bucket,
|
215
|
+
project_name: project_name,
|
216
|
+
file_path: file.file_path,
|
217
|
+
new_bucket_name: dest_bucket,
|
218
|
+
new_file_path: file.file_path,
|
219
|
+
create_parent: true)
|
220
|
+
)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Now delete the source folder
|
224
|
+
delete_folder(
|
225
|
+
Etna::Clients::Metis::DeleteFolderRequest.new(
|
226
|
+
project_name: project_name,
|
227
|
+
bucket_name: source_bucket,
|
228
|
+
folder_path: folder.folder_path
|
229
|
+
))
|
230
|
+
end
|
231
|
+
|
232
|
+
private
|
233
|
+
|
234
|
+
def parent_folder_path(folder_path)
|
235
|
+
folder_path.split('/')[0..-2].join('/')
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,313 @@
|
|
1
|
+
require_relative '../../json_serializable_struct'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Etna
|
5
|
+
module Clients
|
6
|
+
class Metis
|
7
|
+
class ListFoldersRequest < Struct.new(:project_name, :bucket_name, :offset, :limit, keyword_init: true)
|
8
|
+
include JsonSerializableStruct
|
9
|
+
|
10
|
+
def initialize(**params)
|
11
|
+
super({}.update(params))
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_h
|
15
|
+
# The :project_name comes in from Polyphemus as a symbol value,
|
16
|
+
# we need to make sure it's a string because it's going
|
17
|
+
# in the URL.
|
18
|
+
super().compact.transform_values(&:to_s)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class RenameFolderRequest < Struct.new(:project_name, :bucket_name, :folder_path, :new_bucket_name, :new_folder_path, :create_parent, keyword_init: true)
|
23
|
+
include JsonSerializableStruct
|
24
|
+
|
25
|
+
def initialize(**params)
|
26
|
+
super({create_parent: false}.update(params))
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_h
|
30
|
+
# The :project_name comes in from Polyphemus as a symbol value,
|
31
|
+
# we need to make sure it's a string because it's going
|
32
|
+
# in the URL.
|
33
|
+
super().compact.transform_values(&:to_s)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class RenameFileRequest < Struct.new(:project_name, :bucket_name, :file_path, :new_bucket_name, :new_file_path, :create_parent, keyword_init: true)
|
38
|
+
include JsonSerializableStruct
|
39
|
+
|
40
|
+
def initialize(**params)
|
41
|
+
super({create_parent: false}.update(params))
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_h
|
45
|
+
# The :project_name comes in from Polyphemus as a symbol value,
|
46
|
+
# we need to make sure it's a string because it's going
|
47
|
+
# in the URL.
|
48
|
+
super().compact.transform_values(&:to_s)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class ListFolderRequest < Struct.new(:project_name, :bucket_name, :folder_path, keyword_init: true)
|
53
|
+
include JsonSerializableStruct
|
54
|
+
|
55
|
+
def initialize(**params)
|
56
|
+
super({}.update(params))
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_h
|
60
|
+
# The :project_name comes in from Polyphemus as a symbol value,
|
61
|
+
# we need to make sure it's a string because it's going
|
62
|
+
# in the URL.
|
63
|
+
super().compact.transform_values(&:to_s)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class CreateFolderRequest < Struct.new(:project_name, :bucket_name, :folder_path, keyword_init: true)
|
68
|
+
include JsonSerializableStruct
|
69
|
+
|
70
|
+
def initialize(**params)
|
71
|
+
super({}.update(params))
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_h
|
75
|
+
# The :project_name comes in from Polyphemus as a symbol value,
|
76
|
+
# we need to make sure it's a string because it's going
|
77
|
+
# in the URL.
|
78
|
+
super().compact.transform_values(&:to_s)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class DeleteFolderRequest < Struct.new(:project_name, :bucket_name, :folder_path, keyword_init: true)
|
83
|
+
include JsonSerializableStruct
|
84
|
+
|
85
|
+
def initialize(**params)
|
86
|
+
super({}.update(params))
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_h
|
90
|
+
# The :project_name comes in from Polyphemus as a symbol value,
|
91
|
+
# we need to make sure it's a string because it's going
|
92
|
+
# in the URL.
|
93
|
+
super().compact.transform_values(&:to_s)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class FindRequest < Struct.new(:project_name, :bucket_name, :limit, :offset, :params, keyword_init: true)
|
98
|
+
include JsonSerializableStruct
|
99
|
+
|
100
|
+
def initialize(**args)
|
101
|
+
super({params: []}.update(args))
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_param(param)
|
105
|
+
params << param
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_h
|
109
|
+
# The nested :params values don't get converted correctly with transform_values, so it's
|
110
|
+
# easier to do from a JSON string
|
111
|
+
JSON.parse(to_json, :symbolize_names => true)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class FindParam < Struct.new(:attribute, :predicate, :value, :type, keyword_init: true)
|
116
|
+
include JsonSerializableStruct
|
117
|
+
def initialize(**args)
|
118
|
+
super({}.update(args))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class CopyFilesRequest < Struct.new(:project_name, :revisions, keyword_init: true)
|
123
|
+
include JsonSerializableStruct
|
124
|
+
|
125
|
+
def initialize(**args)
|
126
|
+
super({revisions: []}.update(args))
|
127
|
+
end
|
128
|
+
|
129
|
+
def add_revision(revision)
|
130
|
+
revisions << revision
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_h
|
134
|
+
# The nested :revisions values don't get converted correctly with transform_values, so it's
|
135
|
+
# easier to do from a JSON string
|
136
|
+
JSON.parse(to_json, :symbolize_names => true)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class CopyRevision < Struct.new(:source, :dest, keyword_init: true)
|
141
|
+
include JsonSerializableStruct
|
142
|
+
def initialize(**args)
|
143
|
+
super({}.update(args))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class FoldersResponse
|
148
|
+
attr_reader :raw
|
149
|
+
|
150
|
+
def initialize(raw = {})
|
151
|
+
@raw = raw
|
152
|
+
end
|
153
|
+
|
154
|
+
def folders
|
155
|
+
Folders.new(raw[:folders])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class FilesResponse
|
160
|
+
attr_reader :raw
|
161
|
+
|
162
|
+
def initialize(raw = {})
|
163
|
+
@raw = raw
|
164
|
+
end
|
165
|
+
|
166
|
+
def files
|
167
|
+
Files.new(raw[:files])
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class FoldersAndFilesResponse < FoldersResponse
|
172
|
+
def files
|
173
|
+
Files.new(raw[:files])
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class Files
|
178
|
+
attr_reader :raw
|
179
|
+
|
180
|
+
def initialize(raw = {})
|
181
|
+
@raw = raw
|
182
|
+
end
|
183
|
+
|
184
|
+
def all
|
185
|
+
raw.map { |file| File.new(file) }
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
class Folders
|
190
|
+
attr_reader :raw
|
191
|
+
|
192
|
+
def initialize(raw = {})
|
193
|
+
@raw = raw
|
194
|
+
end
|
195
|
+
|
196
|
+
def all
|
197
|
+
raw.map { |folder| Folder.new(folder) }
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class File
|
202
|
+
attr_reader :raw
|
203
|
+
|
204
|
+
def initialize(raw = {})
|
205
|
+
@raw = raw
|
206
|
+
end
|
207
|
+
|
208
|
+
def file_path
|
209
|
+
raw[:file_path]
|
210
|
+
end
|
211
|
+
|
212
|
+
def project_name
|
213
|
+
raw[:project_name]
|
214
|
+
end
|
215
|
+
|
216
|
+
def bucket_name
|
217
|
+
raw[:bucket_name]
|
218
|
+
end
|
219
|
+
|
220
|
+
def download_path
|
221
|
+
raw[:download_url].nil? ?
|
222
|
+
"/#{project_name}/download/#{bucket_name}/#{file_path}" :
|
223
|
+
raw[:download_url].sub(%r!^https://[^/]*?/!, '/')
|
224
|
+
end
|
225
|
+
|
226
|
+
def download_url
|
227
|
+
raw[:download_url] || ''
|
228
|
+
end
|
229
|
+
|
230
|
+
def file_name
|
231
|
+
raw[:file_name]
|
232
|
+
end
|
233
|
+
|
234
|
+
def updated_at
|
235
|
+
time = raw[:updated_at]
|
236
|
+
time.nil? ? nil : Time.parse(time)
|
237
|
+
end
|
238
|
+
|
239
|
+
def size
|
240
|
+
raw[:size]
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class Folder
|
245
|
+
attr_reader :raw
|
246
|
+
|
247
|
+
def initialize(raw = {})
|
248
|
+
@raw = raw
|
249
|
+
end
|
250
|
+
|
251
|
+
def folder_path
|
252
|
+
raw[:folder_path]
|
253
|
+
end
|
254
|
+
|
255
|
+
def bucket_name
|
256
|
+
raw[:bucket_name]
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class AuthorizeUploadRequest < Struct.new(:project_name, :bucket_name, :file_path, keyword_init: true)
|
261
|
+
include JsonSerializableStruct
|
262
|
+
end
|
263
|
+
|
264
|
+
class UploadStartRequest < Struct.new(:file_size, :action, :metis_uid, :next_blob_size, :upload_path, :next_blob_hash, :reset, keyword_init: true)
|
265
|
+
include JsonSerializableStruct
|
266
|
+
|
267
|
+
def initialize(args)
|
268
|
+
super({ action: UploadAction::START }.update(args))
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
class UploadBlobRequest < Struct.new(:file_size, :action, :metis_uid, :blob_data, :upload_path, :next_blob_size, :next_blob_hash, :current_byte_position, keyword_init: true)
|
273
|
+
include MultipartSerializableNestedHash
|
274
|
+
|
275
|
+
def initialize(args)
|
276
|
+
super({ action: UploadAction::BLOB }.update(args))
|
277
|
+
end
|
278
|
+
|
279
|
+
def encode_multipart_content(base_key = '')
|
280
|
+
self.class.encode_multipart_content(to_h, base_key)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class UploadResponse
|
285
|
+
attr_reader :raw
|
286
|
+
def initialize(raw = {})
|
287
|
+
@raw = raw
|
288
|
+
end
|
289
|
+
|
290
|
+
def current_byte_position
|
291
|
+
raw['current_byte_position'].to_i
|
292
|
+
end
|
293
|
+
|
294
|
+
def url
|
295
|
+
raw['url'] || ''
|
296
|
+
end
|
297
|
+
|
298
|
+
def next_blob_size
|
299
|
+
raw['next_blob_size'].to_i
|
300
|
+
end
|
301
|
+
|
302
|
+
def upload_path
|
303
|
+
url.sub(%r!^https://[^/]*?/!, '/')
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class UploadAction < String
|
308
|
+
START = UploadAction.new("start")
|
309
|
+
BLOB = UploadAction.new("blob")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|