holistics 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f4151e165215a9fb3c9b3a6317cd9b9ef829f5e
4
- data.tar.gz: 0f0078f67112c8176971d6cfbce5a8094e901f07
3
+ metadata.gz: a84dcb9a88918717b220f217e544a804ee83ac8d
4
+ data.tar.gz: cedcd80882d85ae412fe1e810ef13afc3e1e7e16
5
5
  SHA512:
6
- metadata.gz: 654ee243f6fb1415300f32f1004563574aef12b3cbdca659dbbe186a34c6f11b98e2792d75847bf8814af6d516eeaacbf661410b1e1d319c8d78e51605c81d60
7
- data.tar.gz: 7a892fa848ef8b5b5ac65b9c5cb55c8166a09d5bc61dfe8a1395fe3a201504fa6a7849afe6a1f87efdef7f85032a9f165db366689102f68047e3ded7346ef297
6
+ metadata.gz: 36a8b5e6de2e778028f8b919b8667439269f41650d874b3177bb05e826d13a407c54238885ff41b5e458fa92daac93d6e9134bbd8ef5b9d70f6c9ae926b7d8a0
7
+ data.tar.gz: 85075130ff88b1fd518a3ab1c5f91eae3403e1e0bb7e37fc8f76e6c3304edbf1a38f8ce304f9e9112152c4f93f430530b2045f67f6ac74f12bc0bd9f4658b1c4
data/holistics.gemspec CHANGED
@@ -14,11 +14,14 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = 'http://rubygems.org/gems/holistics-cli'
15
15
  spec.license = 'GPL'
16
16
 
17
- spec.files = %w[.document holistics.gemspec] + Dir['*.md', 'bin/*', 'lib/**/*.rb']
18
- spec.require_paths = ['lib']
19
-
17
+ spec.files = %w[.document holistics.gemspec] + Dir['*.md', 'bin/*', 'lib/*', 'lib/**/*.rb']
18
+ spec.require_paths << 'lib'
20
19
  spec.executables = ['holistics']
21
20
 
21
+ spec.required_ruby_version = '>= 2.0'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.0"
24
+
22
25
  spec.add_dependency 'activesupport', '~> 4.2'
23
26
  spec.add_dependency 'httparty', '~> 0.13'
24
27
  spec.add_dependency 'thor', '~> 0.19'
@@ -1,27 +1,30 @@
1
1
  require 'httparty'
2
2
  require 'holistics/tabular_formatter'
3
+ require 'yaml'
4
+ require 'json'
3
5
 
4
6
  class ApiClient
5
7
  SERVER_URL = 'https://secure.holistics.io/'
6
8
 
7
9
  def login token
8
- puts 'Authenticating token...'
9
- url = api_url_for('users/info.json', token)
10
- response = HTTParty.get(url)
10
+ puts 'Logging in...'
11
+ response, ok = holistics_authenticate(token)
12
+ if ok
13
+ parsed = JSON.parse(response.body)
14
+ puts 'Authentication successful. Info:'
15
+ puts "- ID: #{parsed['id']}"
16
+ puts "- Email: #{parsed['email']}"
11
17
 
12
- if response.code != 200
13
- puts 'Error authenticating. Please check your token again.'
14
- exit 1
18
+ write_token_to_gconfig(token)
19
+ else
20
+ puts 'Error logging in. Please check your token again.'
15
21
  end
22
+ end
16
23
 
17
- parsed = JSON.parse(response.body)
18
- puts 'Authentication successful. Info:'
19
- puts "- ID: #{parsed['id']}"
20
- puts "- Email: #{parsed['email']}"
21
-
22
- file_path = File.join(ENV['HOME'], '.holistics.yml')
23
-
24
- File.write(file_path, token)
24
+ def holistics_authenticate(token)
25
+ url = api_url_for('users/info.json', token)
26
+ response = HTTParty.get(url)
27
+ return response, (response.code == 200)
25
28
  end
26
29
 
27
30
  def job_show options
@@ -32,12 +35,7 @@ class ApiClient
32
35
  def ds_list
33
36
  url = api_url_for('data_sources.json')
34
37
  response = HTTParty.get(url)
35
-
36
- if response.code != 200
37
- puts "Error retrieving list of data sources. Code: #{response.code}"
38
- puts response.body
39
- exit 1
40
- end
38
+ err_and_exit("Error retrieving list of data sources", response) if response_has_error?(response)
41
39
 
42
40
  parsed = JSON.parse(response.body)
43
41
 
@@ -53,16 +51,12 @@ class ApiClient
53
51
  params = build_submit_params(dest_ds_type, from_ds_type, options)
54
52
  response = submit_transport_job(params)
55
53
 
56
- if response.code != 200
57
- puts "Error submitting transport job. Code: #{response.code}"
58
- puts response.body
59
- exit 1
60
- end
54
+ err_and_exit("Error submitting transport job", response) if response_has_error?(response)
61
55
 
62
56
  parsed = JSON.parse(response.body)
63
57
  job_id = parsed['job_id']
64
- puts "Job submitted. Job ID: #{job_id}."
65
58
 
59
+ puts "Job submitted. Job ID: #{job_id}."
66
60
  tail_job(job_id)
67
61
  end
68
62
 
@@ -102,39 +96,75 @@ class ApiClient
102
96
  end
103
97
 
104
98
  def build_submit_params(dest_ds_type, from_ds_type, options)
105
- params = options.merge(from_ds_type: from_ds_type, dest_ds_type: dest_ds_type, _utoken: get_key)
99
+ params = options.except(:config_path).merge(from_ds_type: from_ds_type, dest_ds_type: dest_ds_type, _utoken: get_token_from_gconfig)
106
100
 
107
101
  configs = {}
108
102
  if options[:config_path]
109
- config_content = File.read(File.join(ENV['ROOT_PATH'], options[:config_path]))
110
- configs = JSON.parse(config_content)
103
+ config_filepath = File.join(ENV['ROOT_PATH'], options[:config_path])
104
+ configs = parse_transport_config(config_filepath)
111
105
  end
112
106
 
113
- configs[:from_table_name] = options[:table_name] if options[:table_name]
114
- configs[:dest_table_name] = options[:rename] if options[:rename]
107
+ configs['from_table_name'] = options[:table_name] if options[:table_name]
108
+ configs['dest_table_name'] = options[:rename] if options[:rename]
115
109
 
116
- params[:config] = configs.to_json # should be a string
110
+ params[:configs] = configs.to_json # should be a string
117
111
  params
118
112
  end
119
113
 
114
+ def parse_transport_config(filepath)
115
+ file_ext = File.extname(filepath).downcase
116
+ if file_ext == '.json'
117
+ return JSON.parse(File.read(filepath))
118
+ elsif file_ext == '.yml'
119
+ return YAML.load(File.read(filepath))
120
+ else
121
+ raise StandardError.new 'Invalid config file extension. Please use either JSON or YML'
122
+ end
123
+ rescue StandardError => e
124
+ STDERR.puts "Error parsing transport config file: #{e.message}"
125
+ exit 1
126
+ end
127
+
120
128
  def authenticated?
121
- File.exists?(config_filepath)
129
+ File.exists?(get_gconfig_filepath)
122
130
  end
123
131
 
124
- def get_key
125
- File.read(config_filepath).strip
132
+ def get_token_from_gconfig
133
+ if authenticated?
134
+ string = YAML.load_file(get_gconfig_filepath)
135
+ string['token']
136
+ else
137
+ raise StandardError.new 'Holistics config file not found'
138
+ end
126
139
  end
127
140
 
128
- def config_filepath
141
+ def get_gconfig_filepath
129
142
  File.expand_path('~/.holistics.yml', __FILE__)
130
143
  end
131
144
 
132
145
  def api_url_for(path, token = nil)
133
- "#{server_url}#{path}?_utoken=#{token || get_key}"
146
+ "#{server_url}#{path}?_utoken=#{token || get_token_from_gconfig}"
134
147
  end
135
148
 
136
149
  def print_log log
137
150
  puts "#{log['created_at'][0..18]} - #{log['level']} - #{log['message']}"
138
151
  end
139
152
 
153
+ def err_and_exit(message, response)
154
+ STDERR.puts message
155
+ STDERR.puts "Error Response Code: #{response.code}"
156
+ STDERR.puts response.body
157
+ exit 1
158
+ end
159
+
160
+ def response_has_error?(response)
161
+ response.code != 200
162
+ end
163
+
164
+ def write_token_to_gconfig(token)
165
+ file_path = File.join(ENV['HOME'], '.holistics.yml')
166
+ h = {'token' => token}
167
+ File.write(file_path, h.to_yaml)
168
+ end
169
+
140
170
  end
@@ -1,3 +1,3 @@
1
1
  class Holistics
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.3'
3
3
  end
data/lib/holistics.rb CHANGED
@@ -13,7 +13,7 @@ end
13
13
  # Either we use other libs, or figure out an elegant way to do it without
14
14
 
15
15
  class HolisticsRunner < Thor
16
- desc 'login', 'Perform authentication'
16
+ desc 'login [auth_token]', 'Perform authentication'
17
17
 
18
18
  def login token
19
19
  client = ApiClient.new
@@ -26,42 +26,55 @@ class HolisticsRunner < Thor
26
26
  ApiClient.new.ds_list
27
27
  end
28
28
 
29
- method_option :from_ds, aliases: '-s', type: :string, required: true, desc: 'From data source (ID)'
30
- method_option :dest_ds, aliases: '-d', type: :string, required: true, desc: 'To data source (ID)'
31
- method_option :table_name, aliases: '-t', type: :string, required: true, desc: 'Table name'
32
- desc 'rs_to_pg', 'Transport data from Amazon Redshift data source to PostgreSQL'
29
+ method_option :from_ds_id, aliases: '-s', type: :string, required: false, desc: 'From data source'
30
+ method_option :dest_ds_id, aliases: '-d', type: :string, required: false, desc: 'To data source'
31
+ method_option :from_table, aliases: '-t', type: :string, required: false, desc: 'Table names'
32
+ method_option :dest_table, aliases: '-n', type: :string, required: false, desc: 'Rename destination table to. Please specify fully qualified name'
33
+ method_option :config_path, aliases: '-c', type: :string, required: false, desc: 'Path to transport config (JSON/YML)̄ file'
34
+ desc 'redshift_to_postgres', 'Transport data from Amazon Redshift data source to PostgreSQL'
33
35
 
34
- def rs_to_pg
36
+ def redshift_to_postgres
35
37
  ApiClient.new.send_transport(:redshift, :postgresql, options.dup)
36
38
  end
37
39
 
38
- method_option :from_ds_id, aliases: '-s', type: :string, required: true, desc: 'From data source'
39
- method_option :dest_ds_id, aliases: '-d', type: :string, required: true, desc: 'To data source'
40
- method_option :table_name, aliases: '-t', type: :string, required: true, desc: 'Table names'
41
- desc 'pg_to_rs', 'Transport data from PostgreSQL to Amazon Redshift'
40
+ method_option :from_ds_id, aliases: '-s', type: :string, required: false, desc: 'From data source'
41
+ method_option :dest_ds_id, aliases: '-d', type: :string, required: false, desc: 'To data source'
42
+ method_option :from_table, aliases: '-t', type: :string, required: false, desc: 'Table names'
43
+ method_option :dest_table, aliases: '-n', type: :string, required: false, desc: 'Rename destination table to. Please specify fully qualified name'
44
+ method_option :config_path, aliases: '-c', type: :string, required: false, desc: 'Path to transport config (JSON/YML)̄ file'
45
+ desc 'postgres_to_redshift', 'Transport data from PostgreSQL to Amazon Redshift'
42
46
 
43
- def pg_to_rs
47
+ def postgres_to_redshift
44
48
  ApiClient.new.send_transport(:postgresql, :redshift, options.dup)
45
49
  end
46
50
 
47
- method_option :from_ds_id, aliases: '-s', type: :string, required: true, desc: 'From data source'
48
- method_option :dest_ds_id, aliases: '-d', type: :string, required: true, desc: 'To data source'
49
- method_option :table_name, aliases: '-t', type: :string, required: true, desc: 'Table names'
50
- method_option :rename, aliases: '-n', type: :string, required: false, desc: 'Rename destination table to. Please specify fully qualified name'
51
- desc 'pg_to_pg', 'Transport data from PostgreSQL to PostgreSQL'
51
+ method_option :from_ds_id, aliases: '-s', type: :string, required: false, desc: 'From data source'
52
+ method_option :dest_ds_id, aliases: '-d', type: :string, required: false, desc: 'To data source'
53
+ method_option :from_table, aliases: '-t', type: :string, required: false, desc: 'Table names'
54
+ method_option :dest_table, aliases: '-n', type: :string, required: false, desc: 'Rename destination table to. Please specify fully qualified name'
55
+ method_option :config_path, aliases: '-c', type: :string, required: false, desc: 'Path to transport config (JSON/YML)̄ file'
56
+ desc 'postgres_to_postgres', 'Transport data from PostgreSQL to PostgreSQL'
52
57
 
53
- def pg_to_pg
58
+ def postgres_to_postgres
54
59
  ApiClient.new.send_transport(:postgresql, :postgresql, options.dup)
55
60
  end
56
61
 
57
- method_option :config_path, aliases: '-c', type: :string, required: true, desc: 'Path to transport config (JSON) file'
62
+ method_option :from_ds_id, aliases: '-s', type: :string, required: false, desc: 'From data source'
63
+ method_option :dest_ds_id, aliases: '-d', type: :string, required: false, desc: 'To data source'
64
+ method_option :from_table, aliases: '-t', type: :string, required: false, desc: 'Table names'
65
+ method_option :dest_table, aliases: '-n', type: :string, required: false, desc: 'Rename destination table to. Please specify fully qualified name'
66
+ method_option :config_path, aliases: '-c', type: :string, required: false, desc: 'Path to transport config (JSON/YML)̄ file'
58
67
  desc 'mysql_to_postgres', 'Transport data from MySQL to Postgres'
59
68
 
60
69
  def mysql_to_postgres
61
70
  ApiClient.new.send_transport(:mysql, :postgresql, options.dup)
62
71
  end
63
72
 
64
- method_option :config_path, aliases: '-c', type: :string, required: true, desc: 'Path to transport config (JSON) file'
73
+ method_option :from_ds_id, aliases: '-s', type: :string, required: false, desc: 'From data source'
74
+ method_option :dest_ds_id, aliases: '-d', type: :string, required: false, desc: 'To data source'
75
+ method_option :from_table, aliases: '-t', type: :string, required: false, desc: 'Table names'
76
+ method_option :dest_table, aliases: '-n', type: :string, required: false, desc: 'Rename destination table to. Please specify fully qualified name'
77
+ method_option :config_path, aliases: '-c', type: :string, required: false, desc: 'Path to transport config (JSON/YML)̄ file'
65
78
  desc 'mysql_to_redshift', 'Transport data from MySQL to Redshift'
66
79
 
67
80
  def mysql_to_redshift
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: holistics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thanh Dinh Khac
@@ -11,6 +11,20 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2015-11-16 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: activesupport
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -77,11 +91,12 @@ post_install_message:
77
91
  rdoc_options: []
78
92
  require_paths:
79
93
  - lib
94
+ - lib
80
95
  required_ruby_version: !ruby/object:Gem::Requirement
81
96
  requirements:
82
97
  - - ">="
83
98
  - !ruby/object:Gem::Version
84
- version: '0'
99
+ version: '2.0'
85
100
  required_rubygems_version: !ruby/object:Gem::Requirement
86
101
  requirements:
87
102
  - - ">="