dears3 0.0.2 → 0.1.0
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/.aws.json +1 -0
- data/README.md +9 -11
- data/dears3.gemspec +2 -0
- data/lib/dears3.rb +1 -1
- data/lib/dears3/authentication.rb +32 -0
- data/lib/dears3/cli/authentication_helper.rb +53 -0
- data/lib/dears3/cli/client_helper.rb +116 -0
- data/lib/dears3/cli/s3.rb +44 -27
- data/lib/dears3/client.rb +98 -63
- data/lib/dears3/version.rb +1 -1
- data/spec/authentication_spec.rb +18 -0
- data/spec/client_spec.rb +13 -0
- data/spec/spec_helper.rb +24 -0
- metadata +41 -4
- data/lib/dears3/auth.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4744ddc0b3362fc28d2fea6baec07d58463377ca
|
4
|
+
data.tar.gz: 7425662978d73e2f15c08ef4a8636d7970555ab9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76cd5e1d5b83ca35ea38eae584358bef6ca8a8b4716f557d5c8b968cf6a8f1647d6bfed71c55c3f02c6603d1ed15ae9c43c00e90248ef964873e286837f55276
|
7
|
+
data.tar.gz: 10219a8b43a77c44ccd496e8a496e8540db857b38f73a73e3ac2d2f6f97e238750b9fca5b38b0a92c34a50dfbfde0057299030aaba4448a58e3400b29de4e964
|
data/.aws.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"access_key_id":"AKIAIQEZRNEZX5DG2AEQ","secret_access_key":"BwDssTdj48Fe1o3KDu5VmeoyiuZJmWYlFtHEmq1j"}
|
data/README.md
CHANGED
@@ -6,7 +6,8 @@ Command line tools to mirror your current directory in an AWS bucket.
|
|
6
6
|
|
7
7
|
**Installation**
|
8
8
|
|
9
|
-
Run `gem install dears3` from the command line. Only works on *NIX systems
|
9
|
+
Run `gem install dears3` from the command line. Only works on *NIX systems for
|
10
|
+
now.
|
10
11
|
|
11
12
|
**AWS Credentials**
|
12
13
|
|
@@ -40,25 +41,22 @@ bucket. Any file beginning with "." is ignored. It syncs to arbitary levels of
|
|
40
41
|
nesting so be careful with symlinks that could cause an infinite loop.
|
41
42
|
|
42
43
|
The bucket will take the name of the current directory, replacing underscores
|
43
|
-
with dashes.
|
44
|
-
|
44
|
+
with dashes. If the bucket name is invalid or unavaiable, you will be prompted
|
45
|
+
to specify the bucket's name.
|
45
46
|
|
46
47
|
*Caution: If a bucket with that name already exists and contains files with the
|
47
|
-
same names as the files in your directory, those files will be overriden
|
48
|
-
warning.*
|
49
|
-
|
50
|
-
Run `s3 upload --publish` to publish your uploaded files as a website.
|
48
|
+
same names as the files in your directory, those files will be overriden.*
|
51
49
|
|
52
50
|
**s3 publish**
|
53
51
|
|
54
|
-
Publishes the current directory as a website.
|
55
|
-
|
56
|
-
|
52
|
+
Publishes the current directory as a website. Requires at least one file in the
|
53
|
+
directory to be uploaded.
|
57
54
|
|
58
55
|
## Contributing
|
59
56
|
|
60
|
-
1. Fork it ( https://github.com/
|
57
|
+
1. Fork it ( https://github.com/7imon7ays/dears3/fork )
|
61
58
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
62
59
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
63
60
|
4. Push to the branch (`git push origin my-new-feature`)
|
64
61
|
5. Create a new Pull Request
|
62
|
+
|
data/dears3.gemspec
CHANGED
data/lib/dears3.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'oj'
|
3
|
+
require 'thor'
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
class DearS3::Authentication
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
# TODO: Give option to upload once without storing credentials.
|
10
|
+
def connect
|
11
|
+
# TODO: Raise error if no credentials file available
|
12
|
+
::AWS::S3.new aws_credentials
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_credentials_file! credentials
|
16
|
+
File.open credentials_path, "w" do |f|
|
17
|
+
f.write credentials.to_json
|
18
|
+
f.write "\n"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def aws_credentials
|
25
|
+
::Oj.load File.read credentials_path
|
26
|
+
end
|
27
|
+
|
28
|
+
def credentials_path
|
29
|
+
File.expand_path '~/.aws.json'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module DearS3
|
2
|
+
class Cli
|
3
|
+
class AuthenticationHelper
|
4
|
+
include ::Thor::Shell
|
5
|
+
|
6
|
+
def initialize authentication
|
7
|
+
@authentication = authentication
|
8
|
+
end
|
9
|
+
|
10
|
+
def connect
|
11
|
+
begin
|
12
|
+
authentication.connect
|
13
|
+
rescue Errno::ENOENT
|
14
|
+
say "Credentials file not found. Please run 's3:auth' to authenticate.", :red
|
15
|
+
abort
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def save_credentials! credentials
|
20
|
+
authentication.create_credentials_file! credentials
|
21
|
+
end
|
22
|
+
|
23
|
+
def maybe_get_credentials
|
24
|
+
if File.exists?(credentials_path) && !override_credentials?
|
25
|
+
nil
|
26
|
+
else
|
27
|
+
request_credentials
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :authentication
|
34
|
+
|
35
|
+
def request_credentials
|
36
|
+
access_key_id = ask "Please enter your AWS access key id:"
|
37
|
+
secret_access_key = ask "Please enter your AWS secret access key:", echo: false
|
38
|
+
say
|
39
|
+
|
40
|
+
{ access_key_id: access_key_id, secret_access_key: secret_access_key }
|
41
|
+
end
|
42
|
+
|
43
|
+
def override_credentials?
|
44
|
+
choice = ask("Override existing '.aws.json' file? (y/n):")
|
45
|
+
%w( y yes Y ok OK ).include? choice
|
46
|
+
end
|
47
|
+
|
48
|
+
def credentials_path
|
49
|
+
File.expand_path '~/.aws.json'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module DearS3
|
2
|
+
class Cli
|
3
|
+
class ClientHelper
|
4
|
+
include ::Thor::Shell
|
5
|
+
|
6
|
+
def initialize s3_client
|
7
|
+
@s3_client = s3_client
|
8
|
+
|
9
|
+
name = get_bucket_name
|
10
|
+
|
11
|
+
s3_client.set_bucket name
|
12
|
+
end
|
13
|
+
|
14
|
+
def upload
|
15
|
+
bucket_name = s3_client.bucket_name
|
16
|
+
|
17
|
+
say "Uploading files to bucket '#{ bucket_name }'."
|
18
|
+
|
19
|
+
begin
|
20
|
+
s3_client.walk_and_upload ".", status_proc
|
21
|
+
rescue ::AWS::S3::Errors::Forbidden
|
22
|
+
alert_access_denied
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
say "Done syncing bucket."
|
26
|
+
end
|
27
|
+
|
28
|
+
def current_dir_to_bucket_name
|
29
|
+
File.basename(Dir.getwd).gsub('_', '-')
|
30
|
+
end
|
31
|
+
|
32
|
+
def publish
|
33
|
+
bucket_files = s3_client.files_in_bucket
|
34
|
+
|
35
|
+
if bucket_files.empty?
|
36
|
+
abort "Bucket is empty. Please upload at least one file before publishing"
|
37
|
+
end
|
38
|
+
|
39
|
+
say "Files currently in your bucket:"
|
40
|
+
say bucket_files.join(" | "), :green
|
41
|
+
index_doc = request_doc "Pick your bucket's index document:"
|
42
|
+
error_doc = request_doc "Pick your bucket's error document:"
|
43
|
+
|
44
|
+
say "Publishing your bucket. This may take a while..."
|
45
|
+
bucket_url = s3_client.configure_website index_doc, error_doc
|
46
|
+
say "Bucket published at #{ bucket_url }."
|
47
|
+
end
|
48
|
+
|
49
|
+
def unpublish
|
50
|
+
bucket_url = s3_client.remove_website
|
51
|
+
say "Removed #{ bucket_url } from the web."
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
attr_reader :s3_client
|
57
|
+
|
58
|
+
def get_bucket_name
|
59
|
+
bucket_name = default_bucket_name
|
60
|
+
|
61
|
+
if s3_client.validate_bucket_name(bucket_name)
|
62
|
+
bucket_name = ask "Please select your bucket's name:"
|
63
|
+
end
|
64
|
+
|
65
|
+
while error = s3_client.validate_bucket_name(bucket_name)
|
66
|
+
bucket_name = ask "#{ error } bucket name. Please select another:"
|
67
|
+
end
|
68
|
+
|
69
|
+
if s3_client.new_bucket? bucket_name
|
70
|
+
choice = ask "Creating new bucket '#{ bucket_name }'. Continue? (y/n/abort)" end
|
71
|
+
|
72
|
+
return get_bucket_name if %w( n no N No NO ).include? choice
|
73
|
+
exit if choice == "abort"
|
74
|
+
|
75
|
+
bucket_name
|
76
|
+
end
|
77
|
+
|
78
|
+
def default_bucket_name
|
79
|
+
File.basename(Dir.getwd).gsub('_', '-').downcase
|
80
|
+
end
|
81
|
+
|
82
|
+
def request_doc request_message
|
83
|
+
doc = ask request_message
|
84
|
+
files_in_bucket = s3_client.files_in_bucket
|
85
|
+
|
86
|
+
until files_in_bucket.include? doc
|
87
|
+
say "No such file in your bucket. Please choose one from this list:"
|
88
|
+
doc = ask files_in_bucket.join(" | ") + "\n", :green
|
89
|
+
end
|
90
|
+
|
91
|
+
doc
|
92
|
+
end
|
93
|
+
|
94
|
+
def alert_access_denied
|
95
|
+
say "Access denied!", :red
|
96
|
+
say "Make sure your credentials are correct and your bucket name isn't already taken by someone else."
|
97
|
+
say "Note: AWS bucket names are shared across all users."
|
98
|
+
say
|
99
|
+
end
|
100
|
+
|
101
|
+
def status_proc
|
102
|
+
# TODO: Confirm overriding files
|
103
|
+
Proc.new do |entry, status|
|
104
|
+
case status
|
105
|
+
when :unchanged
|
106
|
+
say "\tUnchanged: #{ entry }", :blue
|
107
|
+
when :update
|
108
|
+
say "\tUpdating: '#{ entry }'", :yellow
|
109
|
+
when :upload
|
110
|
+
say "\tUploading: '#{ entry }'", :green
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/dears3/cli/s3.rb
CHANGED
@@ -1,39 +1,56 @@
|
|
1
|
+
require 'dears3/cli/authentication_helper'
|
2
|
+
require 'dears3/cli/client_helper'
|
1
3
|
require 'thor'
|
2
4
|
|
3
5
|
module DearS3
|
4
6
|
class Cli
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
s3_upload.sync "."
|
12
|
-
s3_upload.configure_website if options[:publish]
|
13
|
-
end
|
7
|
+
class S3 < Thor
|
8
|
+
desc "upload", "Deploy current and nested directories to S3"
|
9
|
+
def upload
|
10
|
+
client_helper.upload
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
options[:off] ?
|
20
|
-
s3_upload.remove_website : s3_upload.configure_website
|
21
|
-
end
|
13
|
+
desc "publish", "Publish bucket as a website"
|
14
|
+
def publish
|
15
|
+
client_helper.publish
|
16
|
+
end
|
22
17
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
18
|
+
desc "unpublish", "Take bucket off the www"
|
19
|
+
def unpublish
|
20
|
+
client_helper.unpublish
|
21
|
+
end
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
desc "auth", "Save AWS credentials in home directory"
|
24
|
+
def auth
|
25
|
+
# If credentials file already exists and user doesn't
|
26
|
+
# choose to override, do nothing.
|
27
|
+
if credentials = authentication_helper.maybe_get_credentials
|
28
|
+
authentication_helper.save_credentials! credentials
|
35
29
|
end
|
36
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def client_helper
|
35
|
+
@client_helper ||= ClientHelper.new s3_client
|
36
|
+
end
|
37
|
+
|
38
|
+
def s3_client
|
39
|
+
@s3_client ||= DearS3::Client.instance.with s3_connection
|
40
|
+
end
|
41
|
+
|
42
|
+
def s3_connection
|
43
|
+
authentication.connect
|
44
|
+
end
|
45
|
+
|
46
|
+
def authentication_helper
|
47
|
+
@auhentication_helper ||= DearS3::Cli::AuthenticationHelper.new authentication
|
48
|
+
end
|
49
|
+
|
50
|
+
def authentication
|
51
|
+
@authentication ||= DearS3::Authentication.instance
|
52
|
+
end
|
53
|
+
end
|
37
54
|
end
|
38
55
|
end
|
39
56
|
|
data/lib/dears3/client.rb
CHANGED
@@ -2,40 +2,81 @@ require 'aws-sdk'
|
|
2
2
|
require 'thor'
|
3
3
|
require 'digest/md5'
|
4
4
|
require 'mime/types'
|
5
|
+
require 'singleton'
|
5
6
|
|
6
7
|
class DearS3::Client
|
7
|
-
include
|
8
|
+
include Singleton
|
8
9
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
10
|
+
def set_bucket name
|
11
|
+
self.bucket = s3.buckets[name]
|
12
|
+
|
13
|
+
if new_bucket? name
|
14
|
+
s3.buckets.create(bucket.name, acl: :bucket_owner_full_control)
|
15
|
+
end
|
16
|
+
|
17
|
+
bucket.name
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_bucket_name name
|
21
|
+
return :Invalid if invalid_bucket_name? name
|
22
|
+
return :Unavailable if unavailable_bucket_name? name
|
23
|
+
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def new_bucket? name
|
28
|
+
!s3.buckets[name].exists?
|
29
|
+
end
|
12
30
|
|
13
|
-
|
31
|
+
def bucket_name
|
32
|
+
bucket.name
|
14
33
|
end
|
15
34
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
35
|
+
def with s3_connection
|
36
|
+
@bucket = nil
|
37
|
+
@s3 = s3_connection
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def walk_and_upload path, status_proc = nil
|
42
|
+
entries = Dir.entries path
|
43
|
+
entries.each do |entry|
|
44
|
+
next if entry == File.basename(__FILE__) || entry[0] == '.'
|
45
|
+
nested_entry = (path == "." ? entry : "#{ path }/#{ entry }")
|
46
|
+
if File.directory? nested_entry
|
47
|
+
walk_and_upload nested_entry, status_proc
|
48
|
+
next
|
49
|
+
else
|
50
|
+
upload nested_entry, status_proc
|
51
|
+
end
|
52
|
+
end
|
20
53
|
end
|
21
54
|
|
22
|
-
def configure_website
|
23
|
-
files = bucket.objects.map { |obj| obj.key }
|
24
|
-
say "Files currently in your bucket:"
|
25
|
-
say files.join(" | "), :green
|
26
|
-
index_doc = ask "Pick your bucket's index document:"
|
27
|
-
error_doc = ask "Pick your bucket's error document:"
|
28
|
-
say "Publishing your bucket. This may take a while..."
|
55
|
+
def configure_website index_doc, error_doc
|
29
56
|
bucket.configure_website do |cfg|
|
30
57
|
cfg.index_document_suffix = index_doc
|
31
|
-
cfg.error_document_key = error_doc
|
58
|
+
cfg.error_document_key = error_doc
|
32
59
|
end
|
33
|
-
|
60
|
+
|
61
|
+
bucket.policy = generate_policy
|
62
|
+
# TODO: find more general pattern
|
63
|
+
"http://#{ bucket_name }.s3-website-us-east-1.amazonaws.com/"
|
64
|
+
end
|
65
|
+
|
66
|
+
def generate_policy
|
67
|
+
policy = AWS::S3::Policy.new
|
68
|
+
resources = "arn:aws:s3:::#{ bucket_name }/*"
|
69
|
+
policy.allow(actions: [:get_object], resources: resources, principals: :any)
|
70
|
+
policy
|
71
|
+
end
|
72
|
+
|
73
|
+
def files_in_bucket
|
74
|
+
@files_in_bucket ||= bucket.objects.map &:key
|
34
75
|
end
|
35
76
|
|
36
77
|
def remove_website
|
37
78
|
bucket.remove_website_configuration
|
38
|
-
|
79
|
+
bucket.url
|
39
80
|
end
|
40
81
|
|
41
82
|
private
|
@@ -43,59 +84,53 @@ class DearS3::Client
|
|
43
84
|
attr_accessor :bucket
|
44
85
|
attr_reader :s3
|
45
86
|
|
46
|
-
def
|
47
|
-
|
48
|
-
# see https://forums.aws.amazon.com/thread.jspa?messageID=570880
|
49
|
-
bucket_name = File.basename(Dir.getwd).gsub '_', '-'
|
50
|
-
self.bucket = s3.buckets[bucket_name]
|
87
|
+
def upload entry, status_proc = nil
|
88
|
+
object = bucket.objects[entry]
|
51
89
|
|
52
|
-
|
53
|
-
|
54
|
-
|
90
|
+
if object.exists? && entry_is_unchanged?(entry, object)
|
91
|
+
status_proc.call entry, :unchanged
|
92
|
+
elsif object.exists?
|
93
|
+
status_proc.call entry, :update
|
94
|
+
else
|
95
|
+
status_proc.call entry, :upload
|
55
96
|
end
|
97
|
+
|
98
|
+
content_type = ::MIME::Types.type_for(entry).to_s
|
99
|
+
object.write File.open entry, content_type: content_type
|
56
100
|
end
|
57
101
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
nested_entry = (path == "." ? entry : "#{ path }/#{ entry }")
|
63
|
-
if File.directory? nested_entry
|
64
|
-
walk_and_upload nested_entry
|
65
|
-
next
|
66
|
-
else
|
67
|
-
upload nested_entry
|
68
|
-
end
|
69
|
-
end
|
102
|
+
def entry_is_unchanged? entry, object
|
103
|
+
# Is object etag equal to the MD5 digest of the entry?
|
104
|
+
# Strip opening and closing "\" chars from AWS-formatted etag
|
105
|
+
object.etag[1..-2] == ::Digest::MD5.hexdigest(File.read entry)
|
70
106
|
end
|
71
107
|
|
72
|
-
def
|
73
|
-
|
108
|
+
def invalid_bucket_name? name
|
109
|
+
name.length < 3 or
|
110
|
+
name.length > 62 or
|
111
|
+
name[-1] == '-' or
|
112
|
+
name.include?(".") or
|
113
|
+
name.include?(";") or
|
114
|
+
name.include?("-.") or
|
115
|
+
name.include?(".-")
|
116
|
+
end
|
117
|
+
|
118
|
+
def unavailable_bucket_name? name
|
119
|
+
# Try deleting a non-existent object
|
120
|
+
# If the action is forbidden, the bucket exists and is taken
|
121
|
+
forbidden_exceptions = [AWS::S3::Errors::AccessDenied,
|
122
|
+
AWS::S3::Errors::Forbidden]
|
74
123
|
|
124
|
+
rand_key = (0...20).map { ('a'..'z').to_a[rand(26)] }.join
|
75
125
|
begin
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
say "\tUnchanged: #{ entry }", :blue
|
82
|
-
return
|
83
|
-
else
|
84
|
-
# TODO: Confirm overriding files
|
85
|
-
say "\tUpdating: '#{ entry }'", :yellow
|
86
|
-
end
|
87
|
-
else
|
88
|
-
say "\tUploading: '#{ entry }'", :green
|
89
|
-
end
|
90
|
-
content_type = ::MIME::Types.type_for(entry).to_s
|
91
|
-
new_object.write File.open entry, content_type: content_type
|
92
|
-
rescue ::AWS::S3::Errors::Forbidden
|
93
|
-
say "Access denied!", :red
|
94
|
-
say "Make sure your credentials are correct and your bucket name isn't already taken by someone else."
|
95
|
-
say "Note: AWS bucket names are shared across all users."
|
96
|
-
say
|
97
|
-
abort
|
126
|
+
s3.buckets[name].objects[rand_key].delete
|
127
|
+
rescue *forbidden_exceptions
|
128
|
+
return true
|
129
|
+
rescue AWS::S3::Errors::NoSuchBucket
|
130
|
+
return false
|
98
131
|
end
|
132
|
+
|
133
|
+
false
|
99
134
|
end
|
100
135
|
end
|
101
136
|
|
data/lib/dears3/version.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DearS3::Cli::S3 do
|
4
|
+
context "auth" do
|
5
|
+
let(:auth_output) do
|
6
|
+
capture(:stdout) { subject.auth }
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'Confirms with the user before overriding an existing credentials file' do
|
10
|
+
File.any_instance.stub(exists?: true)
|
11
|
+
Thor::Shell::Basic.any_instance.stub(ask: 'y')
|
12
|
+
auth_output.should include "Override existing '.aws.json'?"
|
13
|
+
auth_output.should include "Please enter your AWS access key id:"
|
14
|
+
auth_output.should include "Please enter your AWS secret access key:"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DearS3::Cli::S3 do
|
4
|
+
context "publishing" do
|
5
|
+
let(:output_after_publish) { capture(:stdout) { subject.publish } }
|
6
|
+
|
7
|
+
it 'prompts user for index and error document before publishing' do
|
8
|
+
Thor::Shell::Basic.any_instance.stub(ask: 'foobar')
|
9
|
+
output_after_publish.should include "Files currently in your bucket"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
Bundler.setup
|
6
|
+
|
7
|
+
require 'dears3'
|
8
|
+
|
9
|
+
#AWS.stub!
|
10
|
+
RSpec.configure do |config|
|
11
|
+
def capture(stream)
|
12
|
+
begin
|
13
|
+
stream = stream.to_s
|
14
|
+
eval "$#{stream} = StringIO.new"
|
15
|
+
yield
|
16
|
+
result = eval("$#{stream}").string
|
17
|
+
ensure
|
18
|
+
eval("$#{stream} = #{stream.upcase}")
|
19
|
+
end
|
20
|
+
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dears3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 7imon7ays
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: byebug
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
description:
|
98
126
|
email:
|
99
127
|
executables:
|
@@ -101,6 +129,7 @@ executables:
|
|
101
129
|
extensions: []
|
102
130
|
extra_rdoc_files: []
|
103
131
|
files:
|
132
|
+
- ".aws.json"
|
104
133
|
- Gemfile
|
105
134
|
- LICENSE.txt
|
106
135
|
- README.md
|
@@ -108,10 +137,15 @@ files:
|
|
108
137
|
- bin/s3
|
109
138
|
- dears3.gemspec
|
110
139
|
- lib/dears3.rb
|
111
|
-
- lib/dears3/
|
140
|
+
- lib/dears3/authentication.rb
|
141
|
+
- lib/dears3/cli/authentication_helper.rb
|
142
|
+
- lib/dears3/cli/client_helper.rb
|
112
143
|
- lib/dears3/cli/s3.rb
|
113
144
|
- lib/dears3/client.rb
|
114
145
|
- lib/dears3/version.rb
|
146
|
+
- spec/authentication_spec.rb
|
147
|
+
- spec/client_spec.rb
|
148
|
+
- spec/spec_helper.rb
|
115
149
|
homepage: https://github.com/7imon7ays/DearS3
|
116
150
|
licenses:
|
117
151
|
- MIT
|
@@ -136,4 +170,7 @@ rubygems_version: 2.2.2
|
|
136
170
|
signing_key:
|
137
171
|
specification_version: 4
|
138
172
|
summary: Sync an S3 bucket with your current directory.
|
139
|
-
test_files:
|
173
|
+
test_files:
|
174
|
+
- spec/authentication_spec.rb
|
175
|
+
- spec/client_spec.rb
|
176
|
+
- spec/spec_helper.rb
|
data/lib/dears3/auth.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'aws-sdk'
|
2
|
-
require 'oj'
|
3
|
-
require 'thor'
|
4
|
-
|
5
|
-
class DearS3::Auth
|
6
|
-
include ::Thor::Shell
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@credentials = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
# TODO: Give option to upload once without storing credentials.
|
13
|
-
def connect
|
14
|
-
begin
|
15
|
-
return ::AWS::S3.new aws_credentials
|
16
|
-
rescue Errno::ENOENT
|
17
|
-
say "Credentials file not found. Please run 's3:auth' to authenticate.", :red
|
18
|
-
abort
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def authenticate
|
23
|
-
if confirm_create_credentials_file?
|
24
|
-
request_credentials
|
25
|
-
create_credentials_file!
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def aws_credentials
|
32
|
-
::Oj.load File.read credentials_path
|
33
|
-
end
|
34
|
-
|
35
|
-
def create_credentials_file!
|
36
|
-
File.open credentials_path, "w" do |f|
|
37
|
-
f.write @credentials.to_json
|
38
|
-
f.write "\n"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def request_credentials
|
43
|
-
@credentials[:access_key_id] = ask "Please enter your AWS access key id:"
|
44
|
-
@credentials[:secret_access_key] = ask(
|
45
|
-
"Please enter your AWS secret access key:",
|
46
|
-
echo: false
|
47
|
-
)
|
48
|
-
say
|
49
|
-
end
|
50
|
-
|
51
|
-
def credentials_path
|
52
|
-
File.expand_path "~/.aws.json"
|
53
|
-
end
|
54
|
-
|
55
|
-
def confirm_create_credentials_file?
|
56
|
-
if File.exists? credentials_path
|
57
|
-
override = ask "Override existing '.aws.json' file? (y/n):"
|
58
|
-
override == "y"
|
59
|
-
else
|
60
|
-
true
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|