worochi 0.0.7 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/worochi/agent/{sample.rb → #example.rb} +2 -14
  3. data/lib/worochi/agent/dropbox.rb +3 -13
  4. data/lib/worochi/agent/github.rb +8 -23
  5. data/lib/worochi/agent.rb +46 -18
  6. data/lib/worochi/config/#example.yml +35 -0
  7. data/lib/worochi/config/dropbox.yml +14 -0
  8. data/lib/worochi/config/github.yml +17 -0
  9. data/lib/worochi/config.rb +9 -84
  10. data/lib/worochi/configurator.rb +120 -0
  11. data/lib/worochi/helper/github_helper.rb +111 -0
  12. data/lib/worochi/helper.rb +28 -7
  13. data/lib/worochi/item.rb +5 -3
  14. data/lib/worochi/log.rb +8 -14
  15. data/lib/worochi/oauth.rb +69 -0
  16. data/lib/worochi/version.rb +1 -1
  17. data/lib/worochi.rb +20 -3
  18. data/spec/cassettes/Worochi/_push/pushes_with_agents.yml +512 -0
  19. data/spec/cassettes/Worochi_Agent_Dropbox/_push_item/pushes_it_chunked_if_size_exceeds_limit.yml +1049 -0
  20. data/spec/cassettes/Worochi_Agent_Dropbox/_push_item_chunked/raises_an_error.yml +44 -0
  21. data/spec/cassettes/Worochi_Agent_Dropbox/_push_items/pushes_multiple_items.yml +165 -0
  22. data/spec/cassettes/Worochi_Agent_Dropbox/it_should_behave_like_a_service_agent/_files/raises_error_on_invalid_path.yml +38 -0
  23. data/spec/cassettes/Worochi_Agent_Dropbox/it_should_behave_like_a_service_agent/_files_and_folders/shows_detailed_listing.yml +79 -0
  24. data/spec/cassettes/Worochi_Agent_Dropbox/it_should_behave_like_a_service_agent/_files_and_folders/shows_detailed_listing_including_the_required_fields.yml +79 -0
  25. data/spec/cassettes/Worochi_Agent_Github/_list/works_with_absolute_paths.yml +12 -12
  26. data/spec/cassettes/Worochi_Agent_Github/_repos/lists_the_repos.yml +207 -0
  27. data/spec/cassettes/Worochi_Agent_Github/_source_branch/retrieves_the_master_branch_correctly.yml +6 -6
  28. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/accepts_a_different_relative_path.yml +12 -12
  29. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/contains_file1.yml +12 -12
  30. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/does_not_contain_folder1.yml +12 -12
  31. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/raises_error_on_invalid_path.yml +133 -0
  32. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files_and_folders/contains_folder1_and_file1.yml +24 -24
  33. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files_and_folders/shows_detailed_listing_including_the_required_fields.yml +133 -0
  34. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_folders/accepts_a_different_relative_path.yml +12 -12
  35. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_folders/contains_folder1.yml +12 -12
  36. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_folders/does_not_contain_file1.yml +12 -12
  37. data/spec/cassettes/Worochi_Agent_Github/{_push_all → modifies_the_repo/_push_all}/pushes_a_list_of_items_to_create_a_new_commit.yml +80 -80
  38. data/spec/cassettes/Worochi_Agent_Github/{_push_all → modifies_the_repo/_push_all}/pushes_the_file_to_the_right_place.yml +60 -60
  39. data/spec/cassettes/Worochi_Agent_Github/modifies_the_repo/_push_blob/pushes_the_blob_even_when_it_is_larger_than_block_size.yml +181 -0
  40. data/spec/cassettes/Worochi_Agent_Github/modifies_the_repo/_push_item/pushes_a_single_item_and_makes_a_commit.yml +687 -0
  41. data/spec/cassettes/Worochi_Agent_Github/modifies_the_repo/_stream_blob/streams_the_file_as_an_Base64_JSON_field.yml +181 -0
  42. data/spec/cassettes/Worochi_OAuth/_flow_end/rejects_bad_code.yml +56 -0
  43. data/spec/{helper.rb → spec_helper.rb} +14 -1
  44. data/spec/support/aws_uri_matcher.rb +1 -1
  45. data/spec/support/shared_exampes_for_agents.rb +13 -2
  46. data/spec/support/test_files.rb +4 -4
  47. data/spec/worochi/agent/dropbox_spec.rb +29 -3
  48. data/spec/worochi/agent/github_spec.rb +54 -26
  49. data/spec/worochi/agent_spec.rb +34 -1
  50. data/spec/worochi/config_spec.rb +46 -30
  51. data/spec/worochi/helper/github_helper_spec.rb +94 -0
  52. data/spec/worochi/helper_spec.rb +15 -3
  53. data/spec/worochi/item_spec.rb +9 -6
  54. data/spec/worochi/log_spec.rb +30 -0
  55. data/spec/worochi/oauth_spec.rb +33 -0
  56. data/spec/worochi_spec.rb +25 -1
  57. data/worochi.gemspec +5 -1
  58. metadata +104 -11
  59. data/lib/worochi/helper/github.rb +0 -100
  60. data/spec/worochi/helper/github_spec.rb +0 -57
@@ -1,18 +1,34 @@
1
- require 'aws-sdk' unless Worochi::Config.s3_bucket.nil?
2
-
3
1
  class Worochi
4
2
  # Contains any global helper methods not specific to any individual service.
5
3
  module Helper
6
4
  class << self
7
5
  # Given an S3 path, return the full URL for the corresponding object
8
- # determined using the AWS SDK.
6
+ # determined using the AWS SDK. AWS_SECRET_ACCESS_KEY and
7
+ # AWS_ACCESS_KEY_ID should be present in ENV. The string should be
8
+ # formatted as: `s3:(bucket_name:)path/to/file`.
9
9
  #
10
- # @param path [String]
11
- # @return [URI::HTTP]
10
+ # @param path [String] S3 path
11
+ # @return [URI::HTTPS] URI of the file on S3
12
+ # @example Pre-configured bucket name
13
+ # Worochi::Config.s3_bucket = 'worochi'
14
+ # Worochi::Helper.s3_url('s3:test/path')
15
+ # # => #<URI::HTTPS URL:https://worochi.s3.amazonaws.com/test/path?AWSAccessKeyId=...>
16
+ # @example Custom bucket name
17
+ # Worochi::Helper.s3_url('s3:bucket-name:a/b')
18
+ # # => #<URI::HTTPS URL:https://bucket-name.s3.amazonaws.com/a/b?AWSAccessKeyId=...>
19
+ # @example Invalid syntax
20
+ # Worochi::Helper.s3_url('www.a.com/b.txt')
21
+ # # => Worochi::Error
12
22
  def s3_url(path)
13
- raise Error, 'S3 bucket name is not defined' if Config.s3_bucket.nil?
23
+ raise Error, 'Invalid S3 path' unless is_s3_path?(path)
14
24
  path = path.sub(s3_prefix_re, '')
15
- AWS::S3.new.buckets[Config.s3_bucket].objects[path].url_for(:read)
25
+ if match = /^(.*)\:/.match(path)
26
+ bucket = match[1]
27
+ path = path.sub(/^(.*)\:/, '')
28
+ end
29
+ bucket ||= Config.s3_bucket
30
+ raise Error, 'S3 bucket name is not defined' if bucket.nil?
31
+ AWS::S3.new.buckets[bucket].objects[path].url_for(:read)
16
32
  end
17
33
 
18
34
  # Check if a given path is an S3 path.
@@ -33,4 +49,9 @@ class Worochi
33
49
  end
34
50
  end
35
51
  end
52
+ end
53
+
54
+ # Load all helpers
55
+ Dir[File.join(File.dirname(__FILE__), 'helper/[^#]*.rb')].each do |file|
56
+ require 'worochi/helper/' + File.basename(file, '.rb')
36
57
  end
data/lib/worochi/item.rb CHANGED
@@ -102,8 +102,10 @@ class Worochi
102
102
  if File.file?(source)
103
103
  retrieve_local(source)
104
104
  else
105
- url = Helper.is_s3_path?(source) ? Helper.s3_url(source) : source
106
- retrieve_remote(url)
105
+ if Config.s3_enabled? && Helper.is_s3_path?(source)
106
+ source = Helper.s3_url(source)
107
+ end
108
+ retrieve_remote(source)
107
109
  end
108
110
  end
109
111
 
@@ -118,7 +120,7 @@ class Worochi
118
120
  file
119
121
  end
120
122
 
121
- # Downloads a remote file using {HTTP::Get}.
123
+ # Downloads a remote file using `HTTP::Get`.
122
124
  #
123
125
  # @param file_url [String, URI] the URL of the file
124
126
  # @return [Tempfile] the downloaded file
data/lib/worochi/log.rb CHANGED
@@ -13,8 +13,10 @@ class Worochi
13
13
  }
14
14
  class << self
15
15
  # Initializes the logging system.
16
- def init_log
17
- @logger = Logger.new(STDOUT)
16
+ #
17
+ # @param logdev [IO] target device to log to
18
+ def init(logdev=nil)
19
+ @logger = Logger.new(logdev || Config.logdev)
18
20
  @logger.formatter = proc do |severity, datetime, progname, msg|
19
21
  "[\033[#{SEVERITY_COLOR[severity]}m#{severity}\033[0m]: #{msg}\n"
20
22
  end
@@ -22,30 +24,22 @@ class Worochi
22
24
 
23
25
  # Prints DEBUG messages
24
26
  def debug(message)
25
- return if Worochi::Config.silent?
26
- init_log if @logger.nil?
27
- @logger.debug message
27
+ @logger.debug message unless Worochi::Config.silent?
28
28
  end
29
29
 
30
30
  # Prints WARN messages
31
31
  def warn(message)
32
- return if Worochi::Config.silent?
33
- init_log if @logger.nil?
34
- @logger.warn message
32
+ @logger.warn message unless Worochi::Config.silent?
35
33
  end
36
34
 
37
35
  # Prints INFO messages
38
36
  def info(message)
39
- return if Worochi::Config.silent?
40
- init_log if @logger.nil?
41
- @logger.info message
37
+ @logger.info message unless Worochi::Config.silent?
42
38
  end
43
39
 
44
40
  # Prints ERROR messages
45
41
  def error(message)
46
- return if Worochi::Config.silent?
47
- init_log if @logger.nil?
48
- @logger.error message
42
+ @logger.error message unless Worochi::Config.silent?
49
43
  end
50
44
  end
51
45
  end
@@ -0,0 +1,69 @@
1
+ require 'oauth2'
2
+
3
+ class Worochi
4
+ # Implements OAuth2 authorization code flow for obtaining user tokens.
5
+ class OAuth
6
+ # OAuth2 options.
7
+ # @return [Hashie::Mash]
8
+ attr_accessor :options
9
+
10
+ # The OAuth2 client
11
+ # @return [OAuth2::Client]
12
+ attr_reader :client
13
+
14
+ # @param service [Symbol] service name
15
+ # @param redirect_url [String] callback URL if required
16
+ def initialize(service, redirect_uri=nil)
17
+ @options = Worochi::Config.service_opts(service).oauth
18
+ options.service = service
19
+ options.redirect_uri = redirect_uri
20
+ opts = { site: options.site }
21
+ opts[:authorize_url] = options.authorize_url if options.authorize_url
22
+ opts[:token_url] = options.token_url if options.token_url
23
+ @client = OAuth2::Client.new(id, secret, opts)
24
+ end
25
+
26
+ # Returns the URL to start the authorization flow.
27
+ #
28
+ # @param state [String] optional security verification state
29
+ # @return [String] URL to begin flow
30
+ def flow_start(state=nil)
31
+ client.site = options.site
32
+ opts = { scope: scope }
33
+ opts[:state] = state if state
34
+ opts[:redirect_uri] = options.redirect_uri if options.redirect_uri
35
+ client.auth_code.authorize_url(opts)
36
+ end
37
+
38
+ # Retrieves the token using the temporary authorization code.
39
+ #
40
+ # @param code [String] authorization code from the first part
41
+ # @return [OAuth2::AccessToken] OAuth2 token
42
+ def flow_end(code)
43
+ client.site = options.token_site || options.site
44
+ opts = {}
45
+ opts[:redirect_uri] = options.redirect_uri if options.redirect_uri
46
+ client.auth_code.get_token(code, opts)
47
+ end
48
+
49
+ alias_method :get_token, :flow_end
50
+
51
+ private
52
+ # @return [String] scope
53
+ def scope
54
+ options.scope || ''
55
+ end
56
+
57
+ # @return [String] environmental variable for client ID
58
+ def id
59
+ var = options.id_env || options.service.to_s.upcase + '_ID'
60
+ ENV[var]
61
+ end
62
+
63
+ # @return [String] environmental variable for client secret
64
+ def secret
65
+ var = options.secret_env || options.service.to_s.upcase + '_SECRET'
66
+ ENV[var]
67
+ end
68
+ end
69
+ end
@@ -1,4 +1,4 @@
1
1
  class Worochi
2
2
  # Current version of the gem
3
- VERSION = '0.0.7'
3
+ VERSION = '0.0.10'
4
4
  end
data/lib/worochi.rb CHANGED
@@ -1,9 +1,12 @@
1
+ require 'hashie'
2
+ require 'aws-sdk'
1
3
  require 'worochi/config'
2
4
  require 'worochi/error'
3
5
  require 'worochi/log'
4
- require 'worochi/helper'
5
6
  require 'worochi/item'
6
7
  require 'worochi/agent'
8
+ require 'worochi/oauth'
9
+ require 'worochi/helper'
7
10
 
8
11
  # The main class for the gem. This and the {Agent} class are the main
9
12
  # endpoints for interacting with the remote services.
@@ -16,6 +19,15 @@ class Worochi
16
19
  # @return [Array]
17
20
  attr_reader :agents
18
21
 
22
+ # Initialize configurations and logging.
23
+ #
24
+ # @return [nil]
25
+ def init
26
+ Config.load_yaml
27
+ Log.init
28
+ reset
29
+ end
30
+
19
31
  # Creates a new {Worochi::Agent} and adds it to the list of agents
20
32
  # listening to {Worochi.push} requests.
21
33
  #
@@ -113,9 +125,14 @@ class Worochi
113
125
  # @see Item.open
114
126
  # @see Agent#push
115
127
  def push(origin, opts={})
116
- Log.warn 'No push targets specified' and return false if @agents.empty?
128
+ if @agents.empty?
129
+ Log.warn 'No push targets specified'
130
+ return false
131
+ end
117
132
  @agents.each { |agent| agent.push(origin, opts) }
118
133
  true
119
134
  end
120
135
  end
121
- end
136
+ end
137
+
138
+ Worochi.init