cloud_powers 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -3
- data/.test.env.example +1 -0
- data/cloud_powers.gemspec +2 -2
- data/lib/cloud_powers/creatable.rb +15 -11
- data/lib/cloud_powers/example_objects.rb +88 -0
- data/lib/cloud_powers/helpers/lang_help.rb +33 -9
- data/lib/cloud_powers/helpers/logic_help.rb +28 -9
- data/lib/cloud_powers/helpers/path_help.rb +244 -34
- data/lib/cloud_powers/resource.rb +9 -5
- data/lib/cloud_powers/storage/bucket.rb +217 -0
- data/lib/cloud_powers/storage/local.rb +129 -0
- data/lib/cloud_powers/storage.rb +284 -12
- data/lib/cloud_powers/stubs/aws_stubs.rb +88 -10
- data/lib/cloud_powers/synapse/pipe/stream.rb +9 -11
- data/lib/cloud_powers/synapse/queue/board.rb +2 -1
- data/lib/cloud_powers/synapse/queue.rb +58 -1
- data/lib/cloud_powers/version.rb +1 -1
- data/lib/cloud_powers/zenv.rb +125 -60
- metadata +13 -11
- data/lib/cloud_powers/synapse/broadcast/broadcast.rb +0 -110
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0eca6befe5c9eec2c6467c012fbe341e0152728e
|
4
|
+
data.tar.gz: 8e6e169a6ed75c5c3da387d49e4c635f501e72ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1a9e681a605063b21d71c5b449d5a9385caa655e68304e017dca1e05e02ec0ee500358e5415bcd8cdaff9755250d9f8b5e2a541f732b3b1b26907366bca84fd
|
7
|
+
data.tar.gz: 2d1fb49aa5756d5163163585977a75ed6d2281d7dc1271615cc8f529e4ac44f85e4343b3d2df43c2373ef0b6b4375c0b45685a1dfb4454309342774f2ade951a
|
data/.gitignore
CHANGED
data/.test.env.example
CHANGED
data/cloud_powers.gemspec
CHANGED
@@ -41,8 +41,8 @@ Gem::Specification.new do |spec|
|
|
41
41
|
spec.add_runtime_dependency 'httparty', '~> 0.14'
|
42
42
|
spec.add_runtime_dependency 'rubyzip', '~> 1.2'
|
43
43
|
spec.add_runtime_dependency 'zip-zip', '~> 0.3'
|
44
|
-
spec.add_runtime_dependency 'websocket-eventmachine-server'
|
45
|
-
spec.add_runtime_dependency 'websocket-eventmachine-client'
|
44
|
+
spec.add_runtime_dependency 'websocket-eventmachine-server', '~> 1.0.1'
|
45
|
+
spec.add_runtime_dependency 'websocket-eventmachine-client', '~> 1.2.0'
|
46
46
|
spec.add_runtime_dependency 'workflow'
|
47
47
|
|
48
48
|
spec.add_development_dependency 'bundler', '~> 1.14.3'
|
@@ -83,8 +83,9 @@ module Smash
|
|
83
83
|
|
84
84
|
module AfterHooks
|
85
85
|
# Alternative to <tt>save!()</tt>. This predicate method is based off
|
86
|
-
# the <tt>@linked</tt> i-var and is set to true after it has been
|
87
|
-
# that this resource is a good map to the resource in the
|
86
|
+
# the <tt>@linked</tt> i-var and is set to true after it has been
|
87
|
+
# confirmed that this resource is a good map to the resource in the
|
88
|
+
# cloud.
|
88
89
|
#
|
89
90
|
# Returns
|
90
91
|
# * +Boolean+
|
@@ -92,18 +93,24 @@ module Smash
|
|
92
93
|
!!@linked
|
93
94
|
end
|
94
95
|
|
95
|
-
# An +after_hook+ style method that sends a reqeust to your custom
|
96
|
-
# of the <tt>create_resource</tt> methodallows you to do
|
97
|
-
# create the resource, in the cloud. This method
|
98
|
-
# a <tt>create_resource</tt> method that can handle
|
99
|
-
# your resource. If this piece of the contract
|
100
|
-
# receive a <tt>NoMethodError</tt>.
|
96
|
+
# An +after_hook+ style method that sends a reqeust to your custom
|
97
|
+
# implementation of the <tt>create_resource</tt> methodallows you to do
|
98
|
+
# things after you create the resource, in the cloud. This method
|
99
|
+
# relies on you having a <tt>create_resource</tt> method that can handle
|
100
|
+
# every aspect of creating your resource. If this piece of the contract
|
101
|
+
# isn't obeyed, you will receive a <tt>NoMethodError</tt>.
|
101
102
|
#
|
102
103
|
# Returns
|
103
104
|
# +Boolean+ - +true+ if the resource
|
105
|
+
#
|
106
|
+
# Notes:
|
107
|
+
# * This method relies on you implementing a method called
|
108
|
+
# +create_resource+ in your class. If you don't, this code will still
|
109
|
+
# execute without errors but +@saved+ will remain +false+
|
104
110
|
def save!
|
105
111
|
resp = create_resource if self.respond_to? :create_resource
|
106
112
|
@saved = !resp.nil?
|
113
|
+
resp
|
107
114
|
end
|
108
115
|
|
109
116
|
# Find out if the resource was created
|
@@ -117,6 +124,3 @@ module Smash
|
|
117
124
|
end
|
118
125
|
end
|
119
126
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
'Hey,'.kind_of? Object &&
|
5
|
+
'you guuyyys!'.is_a? String
|
6
|
+
#=> true
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
1.kind_of? Object &&
|
12
|
+
1.is_a? Numeric
|
13
|
+
#=> true
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
person_hash = {
|
19
|
+
name: 'Fredward Mc',
|
20
|
+
nationality: "'MERCA"
|
21
|
+
}
|
22
|
+
person_hash.kind_of? Object &&
|
23
|
+
person_hash.kind_of? Enumerable
|
24
|
+
# => true
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
class Person
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
fredward = Person.new
|
34
|
+
fredward.kind_of? Object &&
|
35
|
+
fredward.is_a? Person
|
36
|
+
#=> true, probably
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
system('compress', 'this.rb', 'and.sh', 'that.js', fredward, -> { some_method })
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
fredward
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
fredward.cats.select do |cat|
|
52
|
+
cat.pays_rent?
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
class Person
|
57
|
+
attr_accessor :name
|
58
|
+
|
59
|
+
def initialize(**opts)
|
60
|
+
@name = opts[:name]
|
61
|
+
end
|
62
|
+
|
63
|
+
def speak(words)
|
64
|
+
"Hi, I'm #{@name} and #{words}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
batman = Person.new(name: 'Bruce')
|
69
|
+
|
70
|
+
|
71
|
+
batman.speak("I'm Batman")
|
72
|
+
=> "Hi, I'm Bruce and I'm Batman"
|
73
|
+
|
74
|
+
|
75
|
+
class Yokl < Person
|
76
|
+
attr_accessor :cats
|
77
|
+
|
78
|
+
def initialize(**opts)
|
79
|
+
super
|
80
|
+
@cats = opts[:cats]
|
81
|
+
end
|
82
|
+
|
83
|
+
def speak(words)
|
84
|
+
"#{super(words).upcase}, YA'LL"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
fredward = Yokl.new(name: 'Fredward Mc', cats: ['bud', 'icehouse', 'miller', 'modelo', 'pabst'])
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Smash
|
2
2
|
module CloudPowers
|
3
3
|
module LangHelp
|
4
|
-
|
5
4
|
# Allows you to modify all keys, including nested, with a block that you pass.
|
6
5
|
# If no block is passed, a copy is returned.
|
7
6
|
#
|
@@ -50,6 +49,33 @@ module Smash
|
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
52
|
+
# Take an Enumerable apart based on a block. This method works like
|
53
|
+
# Array#reject! except it creates 2 new Enumerables of the same type you
|
54
|
+
# started with; One has the rejected elements and the other has the kept.
|
55
|
+
#
|
56
|
+
# Parameters
|
57
|
+
# * +Enumerable+ - The Enumerable object to start with
|
58
|
+
#
|
59
|
+
# Returns
|
60
|
+
# * +Enumerable+ - The extracted elements in the same type of Enumerable
|
61
|
+
# passed as a parameter
|
62
|
+
#
|
63
|
+
# Notes:
|
64
|
+
# * This modifies the Object passed as a parameter and returns another
|
65
|
+
def extract!(enumerable)
|
66
|
+
return enumerable if enumerable.nil?
|
67
|
+
|
68
|
+
if block_given?
|
69
|
+
copy = enumerable.dup
|
70
|
+
|
71
|
+
enumerable.reject! { |k,v| yield k,v }
|
72
|
+
|
73
|
+
copy.respond_to?(:-) ? (copy - enumerable) : copy.keep_if { |k,v| !enumerable.has_key? k }
|
74
|
+
else
|
75
|
+
enumerable
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
53
79
|
# Search through a +Hash+ without knowing if the key is a +String+ or
|
54
80
|
# +Symbol+. A +String+ modification that _normalizes_ each value to compare
|
55
81
|
# is used that is case insensitive. It only leaves word characters, not
|
@@ -198,13 +224,12 @@ module Smash
|
|
198
224
|
# Change strings into an i-var format
|
199
225
|
#
|
200
226
|
# Parameters
|
201
|
-
# *
|
227
|
+
# * key +String+
|
202
228
|
#
|
203
229
|
# Returns
|
204
230
|
# +String+
|
205
|
-
def to_i_var(
|
206
|
-
|
207
|
-
/^\W*@\w+/ =~ var ? to_snake(var) : "@#{to_snake(var)}"
|
231
|
+
def to_i_var(key)
|
232
|
+
"@#{to_snake(key.to_s)}"
|
208
233
|
end
|
209
234
|
|
210
235
|
# Change strings into PascalCase
|
@@ -232,7 +257,7 @@ module Smash
|
|
232
257
|
# * includes ruby file extension
|
233
258
|
# * see #to_snake()
|
234
259
|
def to_ruby_file_name(name)
|
235
|
-
return name if /\w+\.rb$/ =~ name
|
260
|
+
return name if /\w+\.rb$/ =~ name.to_s
|
236
261
|
"#{to_snake(name)}.rb"
|
237
262
|
end
|
238
263
|
|
@@ -249,9 +274,8 @@ module Smash
|
|
249
274
|
# * will not have file extensions
|
250
275
|
# * see #to_ruby_file_name()
|
251
276
|
def to_snake(var)
|
252
|
-
var
|
253
|
-
|
254
|
-
var.gsub(/:{2}|\//, '_').
|
277
|
+
var.to_s.gsub(/^\W*([A-Z|a-z]*)/,'\1').
|
278
|
+
gsub(/:{2}|\//, '_').
|
255
279
|
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
256
280
|
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
257
281
|
gsub(/\s+/, '_').
|
@@ -23,16 +23,15 @@ module Smash
|
|
23
23
|
#
|
24
24
|
# puts @bar
|
25
25
|
# # => 'bar:1475434059'
|
26
|
-
def attr_map(attributes)
|
26
|
+
def attr_map(attributes = self.i_vars)
|
27
27
|
attributes = [attributes, nil] unless attributes.respond_to? :map
|
28
28
|
|
29
29
|
attributes.inject(self) do |this, (attribute, before_value)|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
[attribute, first_place]
|
30
|
+
results = if block_given?
|
31
|
+
first_place, second_place = yield attribute, before_value
|
32
|
+
second_place.nil? ? [attribute, first_place] : [first_place, second_place]
|
34
33
|
else
|
35
|
-
[
|
34
|
+
[attribute, before_value]
|
36
35
|
end
|
37
36
|
|
38
37
|
this.instance_variable_set(to_i_var(results.first), results.last)
|
@@ -45,12 +44,31 @@ module Smash
|
|
45
44
|
# project root is etc.
|
46
45
|
#
|
47
46
|
# Returns
|
48
|
-
# +
|
47
|
+
# * +Pathname+
|
49
48
|
#
|
50
49
|
# Notes
|
51
|
-
# * Uses
|
50
|
+
# * Uses <tt>::#caller()</tt> to figure out where the request came from
|
52
51
|
def called_from
|
53
|
-
|
52
|
+
sanitized_path_string = caller.first.gsub(/:.*/,'')
|
53
|
+
calling_file = File.expand_path(sanitized_path_string)
|
54
|
+
to_realpath(calling_file).parent
|
55
|
+
end
|
56
|
+
|
57
|
+
# Gather up this object's instance variables and create a +Hash+ from the
|
58
|
+
# name/value pairs
|
59
|
+
#
|
60
|
+
# Returns
|
61
|
+
# * +Hash+
|
62
|
+
#
|
63
|
+
# Example
|
64
|
+
# 5class A; attr_accessor :eh; end
|
65
|
+
# a.i_var_hash
|
66
|
+
# => { eh: nil }
|
67
|
+
def i_var_hash
|
68
|
+
self.instance_variables.inject({}) do |hash, (k,v)|
|
69
|
+
hash[k.to_s.gsub('@', '')] = self.instance_variable_get to_i_var(k)
|
70
|
+
hash
|
71
|
+
end
|
54
72
|
end
|
55
73
|
|
56
74
|
# Create an <tt>attr_accessor</tt> feeling getter and setter for an instance
|
@@ -138,6 +156,7 @@ module Smash
|
|
138
156
|
opts = {}
|
139
157
|
opts[:extraInfo] = { message: update }
|
140
158
|
end
|
159
|
+
|
141
160
|
updated_extra_info = opts.delete(:extraInfo) || {}
|
142
161
|
|
143
162
|
{
|
@@ -6,45 +6,52 @@ module Smash
|
|
6
6
|
module CloudPowers
|
7
7
|
module PathHelp
|
8
8
|
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# If no project root has been set by the time this method is called, a new
|
13
|
-
# directory will be created relative to the gem's project root.
|
9
|
+
# Offer a common "path" delimiter. This is designed to allow Storage keep
|
10
|
+
# a common delimiter. It's not required but it makes things a little more
|
11
|
+
# human friendly
|
14
12
|
#
|
15
13
|
# Returns
|
16
14
|
# +String+
|
17
|
-
|
18
|
-
|
19
|
-
# * # If no project root has been set by the time this method is called, a new
|
20
|
-
# directory will be created relative to the gem's project root. This might
|
21
|
-
# have deeper implications than you want to deal with so it's always a good
|
22
|
-
# idea to set your project root as soon as you can.
|
23
|
-
# * TODO: find a way to have this method figure out the actual project's
|
24
|
-
# root, as opposed to just making common <i>"good"</i> assumptions.
|
25
|
-
def job_home
|
26
|
-
string_th = FileUtils.mkdir_p("#{project_root}/lib/jobs/").first
|
27
|
-
@job_home ||= Pathname.new(string_th).realpath.to_s
|
15
|
+
def common_delimiter
|
16
|
+
'/'.freeze
|
28
17
|
end
|
29
18
|
|
30
|
-
#
|
19
|
+
# Expand a +Pathname variable
|
31
20
|
#
|
32
21
|
# Parameters
|
33
|
-
# *
|
22
|
+
# * arg +String+
|
34
23
|
#
|
35
24
|
# Returns
|
36
|
-
# *
|
37
|
-
# '.rb' extension included
|
38
|
-
# * file +String+ if +file+ parameter is not given it will return the
|
39
|
-
# <tt>#job_require_path()</tt>
|
25
|
+
# * +Pathname+ - Absolute path
|
40
26
|
#
|
41
|
-
# Notes
|
42
|
-
# *
|
43
|
-
|
44
|
-
|
45
|
-
|
27
|
+
# Notes:
|
28
|
+
# * This method doesn't guarantee that the path actually exists; It just
|
29
|
+
# gives you a correct, absolute path
|
30
|
+
def expand_path(arg)
|
31
|
+
to_pathname(arg).expand_path
|
46
32
|
end
|
47
33
|
|
34
|
+
# Check if the URL exists
|
35
|
+
#
|
36
|
+
# Parameters
|
37
|
+
# * file +String+
|
38
|
+
#
|
39
|
+
# Returns
|
40
|
+
# +Boolean+
|
41
|
+
def file_exists?(*args)
|
42
|
+
File.exist?(*args.join('/').to_s)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Determine if this path or name seems like a file or a directory
|
46
|
+
#
|
47
|
+
# Parameters
|
48
|
+
# * +Pathname+|+String+
|
49
|
+
#
|
50
|
+
# Returns
|
51
|
+
# * +Boolean+
|
52
|
+
def filename?(pathname)
|
53
|
+
!!(/[A-Za-z]*\.[A-Za-z]+$/ =~ pathname.to_s)
|
54
|
+
end
|
48
55
|
|
49
56
|
# Check if the job file exists in the job directory
|
50
57
|
#
|
@@ -55,14 +62,28 @@ module Smash
|
|
55
62
|
# +Boolean+
|
56
63
|
#
|
57
64
|
# Notes
|
58
|
-
# * See
|
65
|
+
# * See <tt>#job_home()</tt>
|
66
|
+
# * See <tt>#path_exists?()</tt>
|
59
67
|
def job_exist?(file)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
68
|
+
file_exists?(job_home, file)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Gives the path from the project root to lib/jobs[/#{file}.rb]
|
72
|
+
#
|
73
|
+
# Parameters
|
74
|
+
# * file +String+ (optional) (default is '') - name of a file
|
75
|
+
#
|
76
|
+
# Returns
|
77
|
+
# * path/file +String+ if +file+ parameter is given. return has
|
78
|
+
# '.rb' extension included
|
79
|
+
# * file +String+ if +file+ parameter is not given it will return the
|
80
|
+
# <tt>#job_require_path()</tt>
|
81
|
+
#
|
82
|
+
# Notes
|
83
|
+
# * See <tt>#job_home</tt>
|
84
|
+
def job_path(file = '')
|
85
|
+
return job_home if file.empty?
|
86
|
+
to_pathname(job_home, file)
|
66
87
|
end
|
67
88
|
|
68
89
|
# Gives the path from the project root to lib/jobs[/file]
|
@@ -78,6 +99,7 @@ module Smash
|
|
78
99
|
# * Neither path nor file will have a file extension
|
79
100
|
# * See <tt>#job_home</tt>
|
80
101
|
def job_require_path(file_name = '')
|
102
|
+
# TODO: refactor to use Pathname as much as possible
|
81
103
|
begin
|
82
104
|
file_sans_extension = File.basename(file_name, '.*')
|
83
105
|
(Pathname.new(job_home) + file_sans_extension).to_s
|
@@ -85,6 +107,194 @@ module Smash
|
|
85
107
|
nil
|
86
108
|
end
|
87
109
|
end
|
110
|
+
|
111
|
+
# Find all <i>directories</i> that match the given string.
|
112
|
+
#
|
113
|
+
# Returns
|
114
|
+
# * +Pathname+ - absolute path
|
115
|
+
#
|
116
|
+
# Notes
|
117
|
+
# * This method is su-looooOOOOOOOw but it's pretty thorough. Fixing that
|
118
|
+
# while keeping it thorough is a high priority but it works. Your best
|
119
|
+
# bet is to try to set the location for things you're looking for, before
|
120
|
+
# you use them. Another alternative is to use a jailed root to run your
|
121
|
+
# project from.
|
122
|
+
def file_search(name, scope = '/**')
|
123
|
+
Pathname.glob("#{scope}/#{name}").select(&:exist?).reject(&:directory?).map(&:realpath)
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def paths_lcd(*paths)
|
128
|
+
unpacked_paths = paths.map { |path| path.to_s.split('/') }.sort
|
129
|
+
shortest_path_dirs = unpacked_paths.first.count # this is the shortest path
|
130
|
+
common_path = []
|
131
|
+
|
132
|
+
(0..shortest_path_dirs).each do |i|
|
133
|
+
if unpacked_paths.first[i] == unpacked_paths.last[i]
|
134
|
+
common_path << unpacked_paths.first[i]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
to_pathname(common_path.join('/'))
|
139
|
+
end
|
140
|
+
|
141
|
+
def paths_gcd(*paths)
|
142
|
+
start_from = paths_lcd(*paths)
|
143
|
+
paths.sort.last.relative_path_from(start_from)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Find all <i>directories</i> that match the given string.
|
147
|
+
#
|
148
|
+
# Returns
|
149
|
+
# * +Pathname+ - absolute path
|
150
|
+
#
|
151
|
+
# Notes
|
152
|
+
# * This method is su-looooOOOOOOOw but it's pretty thorough. Fixing that
|
153
|
+
# while keeping it thorough is a high priority but it works. Your best
|
154
|
+
# bet is to try to set the location for things you're looking for, before
|
155
|
+
# you use them. Another alternative is to use a jailed root to run your
|
156
|
+
# project from.
|
157
|
+
def path_search(name, scope = default_scope)
|
158
|
+
Pathname.glob("#{scope}/#{name}").select(&:exist?).select(&:directory?).map(&:realpath)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Convert a list of arguments to a path-like +String+ object.
|
162
|
+
#
|
163
|
+
# Parameters
|
164
|
+
# * [+Object+[,...]]
|
165
|
+
#
|
166
|
+
# Returns
|
167
|
+
# * +String+
|
168
|
+
def to_path(*args)
|
169
|
+
to_pathname(*args).to_s
|
170
|
+
end
|
171
|
+
|
172
|
+
# Convert a list of arguments to a +Pathname+ object.
|
173
|
+
#
|
174
|
+
# Parameters
|
175
|
+
# * [+String+[,...]]
|
176
|
+
#
|
177
|
+
# Returns
|
178
|
+
# * +Pathname+
|
179
|
+
def to_pathname(*args)
|
180
|
+
args = args.flatten.compact
|
181
|
+
# #join() will create a path that looks like this `//your/path` if the
|
182
|
+
# first argument is the same as the path seperator on your system.
|
183
|
+
first = /^\/+\W*$/ =~ args.first.to_s ? args.shift : ''
|
184
|
+
path_string = args.join('/')
|
185
|
+
path_string = first + path_string
|
186
|
+
Pathname.new(path_string)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Create and/or get the full path to the argument(s)
|
190
|
+
#
|
191
|
+
# Parameters
|
192
|
+
# * +String+(s) - a path or chunks of a path, in order, as +String+s
|
193
|
+
#
|
194
|
+
# Returns
|
195
|
+
# * +Pathname+
|
196
|
+
#
|
197
|
+
# Notes:
|
198
|
+
# * !This method creates paths, even nested paths, if they don't exist!
|
199
|
+
# * !Use <tt>expand_path</tt> if you don't want to create anything but still
|
200
|
+
# need the full path
|
201
|
+
# * See <tt>#to_pathname</tt>
|
202
|
+
# * See <tt>#touch</tt>
|
203
|
+
def to_realpath(*args)
|
204
|
+
begin
|
205
|
+
pathname = to_pathname(*args)
|
206
|
+
pathname.realpath
|
207
|
+
rescue Errno::ENOENT => e
|
208
|
+
logger.debug("#to_realpath(#{pathname}) called from " +
|
209
|
+
"#{caller.first} but the path doesn't exist")
|
210
|
+
to_realpath(touch(pathname))
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Create a file or directory. You don't have to worry if the path exists.
|
215
|
+
#
|
216
|
+
# Parameters
|
217
|
+
# * path +Pathname+|+String+ - path that you would like created
|
218
|
+
#
|
219
|
+
# Returns
|
220
|
+
# * +Pathname+ - path to your new object
|
221
|
+
#
|
222
|
+
# Notes:
|
223
|
+
# * This method assumes you are careful enough not to break your machine
|
224
|
+
# because you might accidentally over-write an existing, important path
|
225
|
+
# with an empty file or directory. That's no different than any other
|
226
|
+
# library, like +FileUtils+ or +Pathname+ but it's worht being said,
|
227
|
+
# just for good measure.
|
228
|
+
def touch(path)
|
229
|
+
pathname = to_pathname(path)
|
230
|
+
filename?(pathname) ? ::FileUtils.touch(pathname) : ::FileUtils.mkdir_p(pathname)
|
231
|
+
to_realpath(pathname)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Offer a common place to operate from, so <tt>CloudPowers</tt> stays tidy.
|
235
|
+
# This method will find out if your project responds to a method called
|
236
|
+
# 'project_root'. If the method exist, it uses it, otherwise, your new
|
237
|
+
# files etc. will be places at <tt>`pwd`/zlib</tt>.
|
238
|
+
#
|
239
|
+
# Returns
|
240
|
+
# * +Pathname+
|
241
|
+
#
|
242
|
+
# Notes:
|
243
|
+
# * See <tt>to_realpath</tt>
|
244
|
+
def zlib_path(object = '')
|
245
|
+
return zlib_home if (object.nil? || object.empty?)
|
246
|
+
to_path(zlib_home, object)
|
247
|
+
end
|
248
|
+
|
249
|
+
private
|
250
|
+
def has_project_root_defined?
|
251
|
+
self.respond_to? :project_root
|
252
|
+
end
|
253
|
+
|
254
|
+
# Gives a common home for jobs to live so they can be easily grouped and
|
255
|
+
# found. This method will create nested directories, based on the
|
256
|
+
# <tt>#project_root()</tt> method and an additional 'lib/jobs' directory.
|
257
|
+
# If no project root has been set by the time this method is called, a new
|
258
|
+
# directory will be created relative to the gem's project root.
|
259
|
+
#
|
260
|
+
# Returns
|
261
|
+
# +Pathname+
|
262
|
+
def job_home
|
263
|
+
path_string = "#{zlib_path}/jobs"
|
264
|
+
@job_home ||= path_search(path_string).first || to_realpath(path_string)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Gives a common home for this project to store or read from. This method
|
268
|
+
# will create nested directories, based on the <tt>#project_root</tt>
|
269
|
+
# method if it exists, or it will create the +zlib+ directory wherever this
|
270
|
+
# method was called from.
|
271
|
+
#
|
272
|
+
# Returns
|
273
|
+
# * +Pathname+
|
274
|
+
#
|
275
|
+
# Notes
|
276
|
+
# * # If no project root has been set by the time this method is called, a new
|
277
|
+
# directory will be created relative to the gem's project root. This might
|
278
|
+
# have deeper implications than you want to deal with so it's always a good
|
279
|
+
# idea to set your project root as soon as you can.
|
280
|
+
# * TODO: find a way to have this method figure out the actual project's
|
281
|
+
# root, as opposed to just making common <i>"good"</i> assumptions.
|
282
|
+
def zlib_home
|
283
|
+
@zlib_home ||= to_realpath(
|
284
|
+
has_project_root_defined? ? project_root + 'zlib' : './zlib'
|
285
|
+
)
|
286
|
+
end
|
287
|
+
|
288
|
+
private
|
289
|
+
def default_scope
|
290
|
+
if self.respond_to? :origin
|
291
|
+
origin
|
292
|
+
elsif self.respond_to? :project_root
|
293
|
+
project_root || proc_cwd || ps_cwd
|
294
|
+
else
|
295
|
+
to_realpath(called_from).parent
|
296
|
+
end
|
297
|
+
end
|
88
298
|
end
|
89
299
|
end
|
90
300
|
end
|
@@ -19,9 +19,11 @@ module Smash
|
|
19
19
|
attr_accessor :name
|
20
20
|
# whether or not a call has been made to the cloud to back this resource
|
21
21
|
attr_accessor :linked
|
22
|
+
# metadata, i.e. tracking on the remote resource that maps to this resource
|
23
|
+
attr_accessor :meta
|
22
24
|
# the ID in the cloud; e.g. ARN for AWS, etc
|
23
25
|
attr_accessor :remote_id
|
24
|
-
#
|
26
|
+
# @tags will be deprecated in V2. Please use @meta
|
25
27
|
attr_accessor :tags
|
26
28
|
# the type of resource this was instantiated as
|
27
29
|
attr_accessor :type
|
@@ -30,14 +32,16 @@ module Smash
|
|
30
32
|
# inherits from this class. The initialize method follows the method
|
31
33
|
# signature for the active record-like pattern being followed throughout
|
32
34
|
# the code
|
33
|
-
def initialize(name:,
|
35
|
+
def initialize(name:, **config)
|
34
36
|
@linked = false
|
35
37
|
@saved = false
|
36
|
-
@client = client
|
37
|
-
@type = to_snake(self.class.name.split('::').last)
|
38
|
+
@client = config[:client]
|
39
|
+
@type = to_snake(config[:named_type] || config[:type] || self.class.name.split('::').last)
|
38
40
|
@call_name = to_snake("#{name}_#{@type}")
|
39
41
|
@name = name
|
40
|
-
@
|
42
|
+
@meta = Array.new # TODO: create a Meta resource and use it here
|
43
|
+
@tags = @meta
|
44
|
+
logger.debug '@tags will be deprecated in V2. Please use @meta'
|
41
45
|
end
|
42
46
|
end
|
43
47
|
end
|