cloud_powers 1.0.1 → 1.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/.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
|