etna 0.1.16 → 0.1.18
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 +63 -0
- data/etna.completion +926 -0
- data/etna_app.completion +133 -0
- data/ext/completions/extconf.rb +20 -0
- data/lib/commands.rb +368 -0
- data/lib/etna.rb +6 -0
- data/lib/etna/application.rb +38 -20
- data/lib/etna/client.rb +60 -29
- 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 +2 -0
- data/lib/etna/clients/magma/client.rb +24 -9
- data/lib/etna/clients/magma/formatting.rb +1 -0
- data/lib/etna/clients/magma/formatting/models_csv.rb +345 -0
- data/lib/etna/clients/magma/models.rb +323 -9
- data/lib/etna/clients/magma/workflows.rb +10 -0
- data/lib/etna/clients/magma/workflows/add_project_models_workflow.rb +78 -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 +117 -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 +447 -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 +178 -0
- data/lib/etna/clients/metis.rb +1 -0
- data/lib/etna/clients/metis/client.rb +207 -5
- data/lib/etna/clients/metis/models.rb +174 -3
- 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 +235 -5
- data/lib/etna/controller.rb +4 -0
- data/lib/etna/environment_scoped.rb +19 -0
- data/lib/etna/generate_autocompletion_script.rb +130 -0
- data/lib/etna/json_serializable_struct.rb +6 -3
- data/lib/etna/logger.rb +0 -3
- data/lib/etna/multipart_serializable_nested_hash.rb +6 -1
- data/lib/etna/route.rb +1 -1
- data/lib/etna/spec/vcr.rb +98 -0
- data/lib/etna/templates/attribute_actions_template.json +43 -0
- data/lib/etna/test_auth.rb +3 -1
- data/lib/etna/user.rb +4 -0
- data/lib/helpers.rb +81 -0
- metadata +47 -7
data/lib/etna.rb
CHANGED
@@ -15,3 +15,9 @@ require_relative './etna/describe_routes'
|
|
15
15
|
require_relative './etna/client'
|
16
16
|
require_relative './etna/symbolize_params'
|
17
17
|
require_relative './etna/spec'
|
18
|
+
require_relative './etna/clients'
|
19
|
+
require_relative './etna/environment_scoped'
|
20
|
+
|
21
|
+
class EtnaApp
|
22
|
+
include Etna::Application
|
23
|
+
end
|
data/lib/etna/application.rb
CHANGED
@@ -4,18 +4,31 @@
|
|
4
4
|
# whenever we want to use it as a container
|
5
5
|
|
6
6
|
require_relative './sign_service'
|
7
|
+
require_relative './command'
|
8
|
+
require_relative './generate_autocompletion_script'
|
7
9
|
require 'singleton'
|
8
10
|
require 'rollbar'
|
9
11
|
|
10
12
|
module Etna::Application
|
11
13
|
def self.included(other)
|
12
14
|
other.include Singleton
|
15
|
+
other.include Etna::CommandExecutor
|
16
|
+
@@application = other
|
17
|
+
|
18
|
+
other.const_set(:GenerateCompletionScript, Class.new(Etna::GenerateCompletionScript))
|
13
19
|
end
|
14
20
|
|
15
21
|
def self.find(klass)
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
namespace = klass.name.split('::').first
|
23
|
+
if (namespace_klass = Kernel.const_get(namespace)) && (namespace_klass.respond_to? :instance)
|
24
|
+
return namespace_klass.instance
|
25
|
+
end
|
26
|
+
|
27
|
+
if @@application
|
28
|
+
return @@application.instance
|
29
|
+
end
|
30
|
+
|
31
|
+
raise "Could not find application instance from #{namespace}, and not subclass of Application found."
|
19
32
|
end
|
20
33
|
|
21
34
|
def self.register(app)
|
@@ -56,8 +69,18 @@ module Etna::Application
|
|
56
69
|
# the application logger is available globally
|
57
70
|
attr_reader :logger
|
58
71
|
|
59
|
-
def config(type)
|
60
|
-
@config
|
72
|
+
def config(type, env = environment)
|
73
|
+
return nil if @config.nil?
|
74
|
+
return nil if @config[env].nil?
|
75
|
+
return nil unless @config[env].is_a?(Hash)
|
76
|
+
@config[env][type]
|
77
|
+
end
|
78
|
+
|
79
|
+
def env_config(env = environment)
|
80
|
+
return nil if @config.nil?
|
81
|
+
return nil if @config[env].nil?
|
82
|
+
return nil unless @config[env].is_a?(Hash)
|
83
|
+
@config[env]
|
61
84
|
end
|
62
85
|
|
63
86
|
def sign
|
@@ -74,23 +97,18 @@ module Etna::Application
|
|
74
97
|
end
|
75
98
|
end
|
76
99
|
|
77
|
-
def run_command(config,
|
78
|
-
cmd =
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
commands[:help].execute
|
100
|
+
def run_command(config, *args, &block)
|
101
|
+
cmd, cmd_args, cmd_kwds = find_command(*args)
|
102
|
+
cmd.setup(config)
|
103
|
+
|
104
|
+
if block_given?
|
105
|
+
return unless yield [cmd, cmd_args]
|
84
106
|
end
|
85
|
-
end
|
86
107
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
[ cmd.name, cmd ]
|
92
|
-
end
|
93
|
-
]
|
108
|
+
cmd.execute(*cmd.fill_in_missing_params(cmd_args), **cmd_kwds)
|
109
|
+
rescue => e
|
110
|
+
Rollbar.error(e)
|
111
|
+
raise
|
94
112
|
end
|
95
113
|
end
|
96
114
|
|
data/lib/etna/client.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'net/http/persistent'
|
2
2
|
require 'net/http/post/multipart'
|
3
3
|
require 'singleton'
|
4
|
+
require 'rack/utils'
|
4
5
|
|
5
6
|
module Etna
|
6
7
|
class Client
|
7
|
-
def initialize(host, token, routes_available: true)
|
8
|
-
@host = host.sub(%r!/$!,'')
|
8
|
+
def initialize(host, token, routes_available: true, persistent: true, ignore_ssl: false)
|
9
|
+
@host = host.sub(%r!/$!, '')
|
9
10
|
@token = token
|
10
|
-
|
11
|
+
@persistent = persistent
|
12
|
+
@ignore_ssl = ignore_ssl
|
11
13
|
|
12
14
|
if routes_available
|
13
15
|
set_routes
|
@@ -23,24 +25,24 @@ module Etna
|
|
23
25
|
|
24
26
|
def multipart_post(endpoint, content, &block)
|
25
27
|
uri = request_uri(endpoint)
|
26
|
-
multipart = Net::HTTP::Post::Multipart.new uri.
|
28
|
+
multipart = Net::HTTP::Post::Multipart.new uri.request_uri, content
|
27
29
|
multipart.add_field('Authorization', "Etna #{@token}")
|
28
30
|
request(uri, multipart, &block)
|
29
31
|
end
|
30
32
|
|
31
|
-
def post(endpoint, params={}, &block)
|
33
|
+
def post(endpoint, params = {}, &block)
|
32
34
|
body_request(Net::HTTP::Post, endpoint, params, &block)
|
33
35
|
end
|
34
36
|
|
35
|
-
def get(endpoint, params={}, &block)
|
37
|
+
def get(endpoint, params = {}, &block)
|
36
38
|
query_request(Net::HTTP::Get, endpoint, params, &block)
|
37
39
|
end
|
38
40
|
|
39
|
-
def options(endpoint, params={}, &block)
|
41
|
+
def options(endpoint, params = {}, &block)
|
40
42
|
query_request(Net::HTTP::Options, endpoint, params, &block)
|
41
43
|
end
|
42
44
|
|
43
|
-
def delete(endpoint, params={}, &block)
|
45
|
+
def delete(endpoint, params = {}, &block)
|
44
46
|
body_request(Net::HTTP::Delete, endpoint, params, &block)
|
45
47
|
end
|
46
48
|
|
@@ -55,12 +57,12 @@ module Etna
|
|
55
57
|
def define_route_helpers
|
56
58
|
@routes.each do |route|
|
57
59
|
next unless route[:name]
|
58
|
-
self.define_singleton_method(route[:name]) do |params={}|
|
60
|
+
self.define_singleton_method(route[:name]) do |params = {}|
|
59
61
|
|
60
62
|
missing_params = (route[:params] - params.keys.map(&:to_s))
|
61
63
|
unless missing_params.empty?
|
62
64
|
raise ArgumentError, "Missing required #{missing_params.size > 1 ?
|
63
|
-
|
65
|
+
'params' : 'param'} #{missing_params.join(', ')}"
|
64
66
|
end
|
65
67
|
|
66
68
|
response = send(route[:method].downcase, route_path(route, params), params)
|
@@ -79,23 +81,29 @@ module Etna
|
|
79
81
|
|
80
82
|
def persistent_connection
|
81
83
|
@http ||= begin
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
84
|
+
http = Net::HTTP::Persistent.new
|
85
|
+
http.read_timeout = 3600
|
86
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @ignore_ssl
|
87
|
+
http
|
88
|
+
end
|
86
89
|
end
|
87
90
|
|
88
91
|
|
89
|
-
def body_request(type, endpoint, params={}, &block)
|
92
|
+
def body_request(type, endpoint, params = {}, &block)
|
90
93
|
uri = request_uri(endpoint)
|
91
|
-
req = type.new(uri.request_uri,request_params)
|
94
|
+
req = type.new(uri.request_uri, request_params)
|
92
95
|
req.body = params.to_json
|
93
96
|
request(uri, req, &block)
|
94
97
|
end
|
95
98
|
|
96
|
-
def query_request(type, endpoint, params={}, &block)
|
99
|
+
def query_request(type, endpoint, params = {}, &block)
|
97
100
|
uri = request_uri(endpoint)
|
98
|
-
|
101
|
+
|
102
|
+
if uri.query
|
103
|
+
uri.query += "&" + URI.encode_www_form(params)
|
104
|
+
else
|
105
|
+
uri.query = URI.encode_www_form(params)
|
106
|
+
end
|
99
107
|
req = type.new(uri.request_uri, request_params)
|
100
108
|
request(uri, req, &block)
|
101
109
|
end
|
@@ -106,9 +114,9 @@ module Etna
|
|
106
114
|
|
107
115
|
def request_params
|
108
116
|
{
|
109
|
-
|
110
|
-
|
111
|
-
|
117
|
+
'Content-Type' => 'application/json',
|
118
|
+
'Accept' => 'application/json, text/*',
|
119
|
+
'Authorization' => "Etna #{@token}"
|
112
120
|
}
|
113
121
|
end
|
114
122
|
|
@@ -116,8 +124,8 @@ module Etna
|
|
116
124
|
status = response.code.to_i
|
117
125
|
if status >= 400
|
118
126
|
msg = response.content_type == 'application/json' ?
|
119
|
-
|
120
|
-
|
127
|
+
json_error(response.body) :
|
128
|
+
response.body
|
121
129
|
raise Etna::Error.new(msg, status)
|
122
130
|
end
|
123
131
|
end
|
@@ -133,14 +141,37 @@ module Etna
|
|
133
141
|
|
134
142
|
def request(uri, data)
|
135
143
|
if block_given?
|
136
|
-
|
137
|
-
|
138
|
-
|
144
|
+
if @persistent
|
145
|
+
persistent_connection.request(uri, data) do |response|
|
146
|
+
status_check!(response)
|
147
|
+
yield response
|
148
|
+
end
|
149
|
+
else
|
150
|
+
verify_mode = @ignore_ssl ?
|
151
|
+
OpenSSL::SSL::VERIFY_NONE :
|
152
|
+
OpenSSL::SSL::VERIFY_PEER
|
153
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: verify_mode) do |http|
|
154
|
+
http.request(data) do |response|
|
155
|
+
status_check!(response)
|
156
|
+
yield response
|
157
|
+
end
|
158
|
+
end
|
139
159
|
end
|
140
160
|
else
|
141
|
-
|
142
|
-
|
143
|
-
|
161
|
+
if @persistent
|
162
|
+
response = persistent_connection.request(uri, data)
|
163
|
+
status_check!(response)
|
164
|
+
return response
|
165
|
+
else
|
166
|
+
verify_mode = @ignore_ssl ?
|
167
|
+
OpenSSL::SSL::VERIFY_NONE :
|
168
|
+
OpenSSL::SSL::VERIFY_PEER
|
169
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: verify_mode) do |http|
|
170
|
+
response = http.request(data)
|
171
|
+
status_check!(response)
|
172
|
+
return response
|
173
|
+
end
|
174
|
+
end
|
144
175
|
end
|
145
176
|
end
|
146
177
|
end
|
data/lib/etna/clients.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'net/http/persistent'
|
2
|
+
require 'net/http/post/multipart'
|
3
|
+
require 'singleton'
|
4
|
+
require_relative '../../client'
|
5
|
+
require_relative './models'
|
6
|
+
|
7
|
+
module Etna
|
8
|
+
module Clients
|
9
|
+
class Janus
|
10
|
+
def initialize(host:, token:, persistent: true, ignore_ssl: false)
|
11
|
+
raise 'Janus client configuration is missing host.' unless host
|
12
|
+
raise 'Janus client configuration is missing token.' unless token
|
13
|
+
@etna_client = ::Etna::Client.new(
|
14
|
+
host,
|
15
|
+
token,
|
16
|
+
routes_available: false,
|
17
|
+
persistent: persistent,
|
18
|
+
ignore_ssl: ignore_ssl)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_project(get_project_request = GetProjectRequest.new)
|
22
|
+
html = nil
|
23
|
+
@etna_client.get(
|
24
|
+
"/project/#{get_project_request.project_name}",
|
25
|
+
get_project_request) do |res|
|
26
|
+
html = res.body
|
27
|
+
end
|
28
|
+
|
29
|
+
HtmlResponse.new(html)
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_project(add_project_request = AddProjectRequest.new)
|
33
|
+
@etna_client.post('/add_project', add_project_request) do |res|
|
34
|
+
# Redirect, no response data
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_user(add_user_request = AddUserRequest.new)
|
39
|
+
@etna_client.post(
|
40
|
+
"/add_user/#{add_user_request.project_name}",
|
41
|
+
add_user_request) do |res|
|
42
|
+
# Redirect, no response data
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_permission(update_permission_request = UpdatePermissionRequest.new)
|
47
|
+
@etna_client.post(
|
48
|
+
"/update_permission/#{update_permission_request.project_name}",
|
49
|
+
update_permission_request) do |res|
|
50
|
+
# Redirect, no response data
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def refresh_token(refresh_token_request = RefreshTokenRequest.new)
|
55
|
+
token = nil
|
56
|
+
@etna_client.get('/refresh_token', refresh_token_request) do |res|
|
57
|
+
token = res.body
|
58
|
+
end
|
59
|
+
|
60
|
+
TokenResponse.new(token)
|
61
|
+
end
|
62
|
+
|
63
|
+
def viewer_token(viewer_token_request = ViewerTokenRequest.new)
|
64
|
+
token = nil
|
65
|
+
@etna_client.get('/viewer_token', viewer_token_request) do |res|
|
66
|
+
token = res.body
|
67
|
+
end
|
68
|
+
|
69
|
+
TokenResponse.new(token)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require_relative '../../json_serializable_struct'
|
3
|
+
|
4
|
+
# TODO: In the near future, I'd like to transition to specifying apis via SWAGGER and generating model stubs from the
|
5
|
+
# common definitions. For nowe I've written them out by hand here.
|
6
|
+
module Etna
|
7
|
+
module Clients
|
8
|
+
class Janus
|
9
|
+
class GetProjectRequest < Struct.new(:project_name, keyword_init: true)
|
10
|
+
include JsonSerializableStruct
|
11
|
+
|
12
|
+
def initialize(**params)
|
13
|
+
super({}.update(params))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class AddProjectRequest < Struct.new(:project_name, :project_name_full, keyword_init: true)
|
18
|
+
include JsonSerializableStruct
|
19
|
+
|
20
|
+
def initialize(**params)
|
21
|
+
super({}.update(params))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class AddUserRequest < Struct.new(:project_name, :email, :name, :role, :privileged, :affiliation, keyword_init: true)
|
26
|
+
include JsonSerializableStruct
|
27
|
+
|
28
|
+
def initialize(**params)
|
29
|
+
super({privileged: false, affiliation: ''}.update(params))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class UpdatePermissionRequest < Struct.new(:project_name, :email, :role, :privileged, :affiliation, keyword_init: true)
|
34
|
+
include JsonSerializableStruct
|
35
|
+
|
36
|
+
def initialize(**params)
|
37
|
+
super({privileged: false, affiliation: ''}.update(params))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class RefreshTokenRequest
|
42
|
+
def map
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ViewerTokenRequest
|
48
|
+
def map
|
49
|
+
[]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class HtmlResponse
|
54
|
+
attr_reader :raw
|
55
|
+
|
56
|
+
def initialize(raw = '')
|
57
|
+
@raw = raw
|
58
|
+
end
|
59
|
+
|
60
|
+
def html
|
61
|
+
@raw
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class TokenResponse
|
66
|
+
attr_reader :raw
|
67
|
+
|
68
|
+
def initialize(raw = '')
|
69
|
+
@raw = raw
|
70
|
+
end
|
71
|
+
|
72
|
+
def token
|
73
|
+
@raw
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/etna/clients/magma.rb
CHANGED
@@ -7,10 +7,19 @@ require_relative './models'
|
|
7
7
|
module Etna
|
8
8
|
module Clients
|
9
9
|
class Magma
|
10
|
-
|
10
|
+
attr_reader :host, :token, :ignore_ssl
|
11
|
+
def initialize(host:, token:, persistent: true, ignore_ssl: false)
|
11
12
|
raise 'Magma client configuration is missing host.' unless host
|
12
13
|
raise 'Magma client configuration is missing token.' unless token
|
13
|
-
@etna_client = ::Etna::Client.new(
|
14
|
+
@etna_client = ::Etna::Client.new(
|
15
|
+
host,
|
16
|
+
token,
|
17
|
+
routes_available: false,
|
18
|
+
persistent: persistent,
|
19
|
+
ignore_ssl: ignore_ssl)
|
20
|
+
@host = host
|
21
|
+
@token = token
|
22
|
+
@ignore_ssl = ignore_ssl
|
14
23
|
end
|
15
24
|
|
16
25
|
# This endpoint returns models and records by name:
|
@@ -20,7 +29,7 @@ module Etna
|
|
20
29
|
# record_names: [ "rn1", "rn2" ], # or "all",
|
21
30
|
# attribute_names: "all"
|
22
31
|
# }
|
23
|
-
def retrieve(retrieval_request)
|
32
|
+
def retrieve(retrieval_request = RetrievalRequest.new)
|
24
33
|
json = nil
|
25
34
|
@etna_client.post('/retrieve', retrieval_request) do |res|
|
26
35
|
json = JSON.parse(res.body)
|
@@ -31,7 +40,7 @@ module Etna
|
|
31
40
|
|
32
41
|
# This 'query' end point is used to fetch data by graph query
|
33
42
|
# See question.rb for more detail
|
34
|
-
def query(query_request)
|
43
|
+
def query(query_request = QueryRequest.new)
|
35
44
|
json = nil
|
36
45
|
@etna_client.post('/query', query_request) do |res|
|
37
46
|
json = JSON.parse(res.body)
|
@@ -40,10 +49,7 @@ module Etna
|
|
40
49
|
QueryResponse.new(json)
|
41
50
|
end
|
42
51
|
|
43
|
-
|
44
|
-
# { model_name: { record_name: { attribute1: 1, attribute2: 2 } } } }
|
45
|
-
# data can also be a File or IO stream
|
46
|
-
def update(update_request)
|
52
|
+
def update(update_request = UpdateRequest.new)
|
47
53
|
json = nil
|
48
54
|
@etna_client.multipart_post('/update', update_request.encode_multipart_content) do |res|
|
49
55
|
json = JSON.parse(res.body)
|
@@ -52,7 +58,16 @@ module Etna
|
|
52
58
|
UpdateResponse.new(json)
|
53
59
|
end
|
54
60
|
|
55
|
-
def
|
61
|
+
def update_json(update_request = UpdateRequest.new)
|
62
|
+
json = nil
|
63
|
+
@etna_client.post('/update', update_request) do |res|
|
64
|
+
json = JSON.parse(res.body)
|
65
|
+
end
|
66
|
+
|
67
|
+
UpdateResponse.new(json)
|
68
|
+
end
|
69
|
+
|
70
|
+
def update_model(update_model_request = UpdateModelRequest.new)
|
56
71
|
json = nil
|
57
72
|
@etna_client.post('/update_model', update_model_request) do |res|
|
58
73
|
json = JSON.parse(res.body)
|