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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9cc966e1561d2a202cfa35dd2cf3147d4ef2b840
4
- data.tar.gz: d371b86048fef80382f4bc6cd61a3a4a5a7d16bf
3
+ metadata.gz: 0eca6befe5c9eec2c6467c012fbe341e0152728e
4
+ data.tar.gz: 8e6e169a6ed75c5c3da387d49e4c635f501e72ef
5
5
  SHA512:
6
- metadata.gz: 2125004e0684f341d86a5c04ad62edeafb44ee8de978a7487518d319594e0ac165296170cdb1930a6e1928814198c9dd67729a9d0ba8cb10d8604a072b94c78a
7
- data.tar.gz: 8fc1f114aa0be9caedd619e611d3e3014ac31c3f55113b0ba661a50f1b014e3996c711c8a108601673044c0b4aca22307b2f308fae73679119a724de192c2b0d
6
+ metadata.gz: d1a9e681a605063b21d71c5b449d5a9385caa655e68304e017dca1e05e02ec0ee500358e5415bcd8cdaff9755250d9f8b5e2a541f732b3b1b26907366bca84fd
7
+ data.tar.gz: 2d1fb49aa5756d5163163585977a75ed6d2281d7dc1271615cc8f529e4ac44f85e4343b3d2df43c2373ef0b6b4375c0b45685a1dfb4454309342774f2ade951a
data/.gitignore CHANGED
@@ -10,7 +10,6 @@
10
10
  **/tmp/
11
11
  **/*.env
12
12
  **/.byebug_history
13
- **/lib/cloud_powers/synapse/.DS_Store
14
- **/.DS_Store
15
- **/./**/.DS_Store
13
+ **/.DS_Store*
16
14
  **/*.swp
15
+ **/*zlib
data/.test.env.example CHANGED
@@ -17,6 +17,7 @@ STATUS_STREAM="e.g. kinesis stream name"
17
17
 
18
18
  # Aws s3 buckets etc
19
19
  JOB_STORAGE="e.g. s3 object name"
20
+ JOBS_STORAGE="same as JOB_STORAGE"
20
21
 
21
22
  # Aws sqs queue addresses
22
23
  BACKLOG_QUEUE_ADDRESS=""
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 confirmed
87
- # that this resource is a good map to the resource in the cloud.
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 implementation
96
- # of the <tt>create_resource</tt> methodallows you to do things after you
97
- # create the resource, in the cloud. This method relies on you having
98
- # a <tt>create_resource</tt> method that can handle every aspect of creating
99
- # your resource. If this piece of the contract isn't obeyed, you will
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
- # * var +String+
227
+ # * key +String+
202
228
  #
203
229
  # Returns
204
230
  # +String+
205
- def to_i_var(var)
206
- var = var.to_s unless var.kind_of? String
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 = var.to_s unless var.kind_of? String
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
- first_place, second_place = yield attribute, before_value if block_given?
31
-
32
- results = if second_place.nil?
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
- [first_place, second_place]
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
- # +String+
47
+ # * +Pathname+
49
48
  #
50
49
  # Notes
51
- # * Uses +$0+ to figure out what the current file is
50
+ # * Uses <tt>::#caller()</tt> to figure out where the request came from
52
51
  def called_from
53
- File.expand_path(File.dirname($0))
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
- # Gives a common home for jobs to live so they can be easily grouped and
10
- # found. This method will create nested directories, based on the
11
- # <tt>#project_root()</tt> method and an additional 'lib/jobs' directory.
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
- # Notes
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
- # Gives the path from the project root to lib/jobs[/#{file}.rb]
19
+ # Expand a +Pathname variable
31
20
  #
32
21
  # Parameters
33
- # * file +String+ (optional) (default is '') - name of a file
22
+ # * arg +String+
34
23
  #
35
24
  # Returns
36
- # * path/file +String+ if +file+ parameter is given. return has
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
- # * See <tt>#job_home</tt>
43
- def job_path(file = '')
44
- return job_home if file.empty?
45
- Pathname.new("#{job_home}/#{file}").to_s
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 +#job_home()+
65
+ # * See <tt>#job_home()</tt>
66
+ # * See <tt>#path_exists?()</tt>
59
67
  def job_exist?(file)
60
- begin
61
- File.new("#{job_home}/#{file}")
62
- true
63
- rescue Errno::ENOENT
64
- false
65
- end
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
- # tracking on the remote resource that maps to this resource
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:, client: nil, **config)
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
- @tags = Array.new
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