Class: Sfn::Provider
- Inherits:
-
Object
- Object
- Sfn::Provider
- Includes:
- Bogo::AnimalStrings
- Defined in:
- lib/sfn/provider.rb
Overview
Remote provider interface
Constant Summary collapse
- STACK_EXPAND_INTERVAL =
Minimum number of seconds to wait before re-expanding in progress stack
45
- STACK_LIST_INTERVAL =
Default interval for refreshing stack list in cache
120
Instance Attribute Summary collapse
-
#async ⇒ TrueClass, FalseClass
readonly
Async updates.
- #cache ⇒ Cache readonly
- #connection ⇒ Miasma::Models::Orchestration readonly
-
#logger ⇒ Logger, NilClass
readonly
Logger in use.
-
#stack_expansion_interval ⇒ Numeric
readonly
Interval between stack expansions.
-
#stack_list_interval ⇒ Numeric
readonly
Interval between stack list updates.
-
#updater ⇒ Thread, NilClass
Stack list updater.
Instance Method Summary collapse
-
#cached_stacks ⇒ String
Json representation of cached stacks.
-
#expand_stack(stack) ⇒ Object
Expand all lazy loaded attributes within stack.
-
#fetch_stacks ⇒ TrueClass
Request stack information and store in cache.
-
#initialize(args = {}) ⇒ Provider
constructor
Create new instance.
-
#remove_stack(stack_id) ⇒ TrueClass, FalseClass
Remove stack from the cache.
-
#save_expanded_stack(stack_id, stack_attributes) ⇒ TrueClass
Store stack attribute changes.
-
#service_for(service) ⇒ Miasma::Model
Build API connection for service type.
- #stack(stack_id) ⇒ Miasma::Orchestration::Stack, NilClass
- #stacks ⇒ Miasma::Orchestration::Stacks
-
#update_stack_list! ⇒ TrueClass, FalseClass
Start async stack list update.
Constructor Details
#initialize(args = {}) ⇒ Provider
Create new instance
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/sfn/provider.rb', line 41 def initialize(args={}) args = args.to_smash unless(args.get(:miasma, :provider)) best_guess = (args[:miasma] || {}).keys.group_by do |key| key.to_s.split('_').first end.sort do |x, y| y.size <=> x.size end.first if(best_guess) provider = best_guess.first.to_sym else raise ArgumentError.new 'Cannot auto determine :provider value for credentials' end else provider = args[:miasma].delete(:provider).to_sym end if(provider == :aws) if(args[:miasma][:region]) args[:miasma][:aws_region] = args[:miasma].delete(:region) end end if(ENV['DEBUG'].to_s.downcase == 'true') log_to = STDOUT else if(Gem.win_platform?) log_to = 'NUL' else log_to = '/dev/null' end end @logger = args.fetch(:logger, Logger.new(log_to)) @stack_expansion_interval = args.fetch(:stack_expansion_interval, STACK_EXPAND_INTERVAL) @stack_list_interval = args.fetch(:stack_list_interval, STACK_LIST_INTERVAL) @connection = Miasma.api( :provider => provider, :type => :orchestration, :credentials => args[:miasma] ) @cache = args.fetch(:cache, Cache.new(:local)) @async = args.fetch(:async, true) @miamsa_args = args[:miasma].dup cache.init(:stacks_lock, :lock, :timeout => 0.1) cache.init(:stacks, :stamped) cache.init(:stack_expansion_lock, :lock, :timeout => 0.1) if(args.fetch(:fetch, false)) async ? update_stack_list! : fetch_stacks end end |
Instance Attribute Details
#async ⇒ TrueClass, FalseClass (readonly)
Returns async updates.
24 25 26 |
# File 'lib/sfn/provider.rb', line 24 def async @async end |
#connection ⇒ Miasma::Models::Orchestration (readonly)
18 19 20 |
# File 'lib/sfn/provider.rb', line 18 def connection @connection end |
#logger ⇒ Logger, NilClass (readonly)
Returns logger in use.
26 27 28 |
# File 'lib/sfn/provider.rb', line 26 def logger @logger end |
#stack_expansion_interval ⇒ Numeric (readonly)
Returns interval between stack expansions.
28 29 30 |
# File 'lib/sfn/provider.rb', line 28 def stack_expansion_interval @stack_expansion_interval end |
#stack_list_interval ⇒ Numeric (readonly)
Returns interval between stack list updates.
30 31 32 |
# File 'lib/sfn/provider.rb', line 30 def stack_list_interval @stack_list_interval end |
#updater ⇒ Thread, NilClass
Returns stack list updater.
22 23 24 |
# File 'lib/sfn/provider.rb', line 22 def updater @updater end |
Instance Method Details
#cached_stacks ⇒ String
Returns json representation of cached stacks.
96 97 98 99 100 |
# File 'lib/sfn/provider.rb', line 96 def cached_stacks fetch_stacks unless @initial_fetch_complete value = cache[:stacks].value value ? MultiJson.dump(MultiJson.load(value).values) : '[]' end |
#expand_stack(stack) ⇒ Object
Expand all lazy loaded attributes within stack
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/sfn/provider.rb', line 140 def (stack) logger.info "Stack expansion requested (#{stack.id})" if((stack.in_progress? && Time.now.to_i - stack.attributes['Cached'].to_i > stack_expansion_interval) || !stack.attributes['Cached']) begin = false cache.locked_action(:stack_expansion_lock) do = true stack.reload stack.data['Cached'] = Time.now.to_i end if() (stack.id, stack.to_json) end rescue => e logger.error "Stack expansion failed (#{stack.id}) - #{e.class}: #{e}" end else logger.info "Stack has been cached within expand interval. Expansion prevented. (#{stack.id})" end end |
#fetch_stacks ⇒ TrueClass
Request stack information and store in cache
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/sfn/provider.rb', line 165 def fetch_stacks cache.locked_action(:stacks_lock) do logger.info "Lock aquired for stack update. Requesting stacks from upstream. (#{Thread.current})" stacks = Hash[ connection.stacks.reload.all.map do |stack| [stack.id, stack.attributes] end ] if(cache[:stacks].value) existing_stacks = MultiJson.load(cache[:stacks].value) # Force common types stacks = MultiJson.load(MultiJson.dump(stacks)) # Remove stacks that have been deleted stale_ids = existing_stacks.keys - stacks.keys stacks = existing_stacks.to_smash.deep_merge(stacks) stale_ids.each do |stale_id| stacks.delete(stale_id) end end cache[:stacks].value = stacks.to_json logger.info 'Stack list has been updated from upstream and cached locally' end @initial_fetch_complete = true end |
#remove_stack(stack_id) ⇒ TrueClass, FalseClass
Remove stack from the cache
126 127 128 129 130 131 132 133 134 135 |
# File 'lib/sfn/provider.rb', line 126 def remove_stack(stack_id) current_stacks = MultiJson.load(cached_stacks) logger.info "Attempting to remove stack from internal cache (#{stack_id})" cache.locked_action(:stacks_lock) do val = current_stacks.delete(stack_id) logger.info "Successfully removed stack from internal cache (#{stack_id})" cache[:stacks].value = MultiJson.dump(current_stacks) !!val end end |
#save_expanded_stack(stack_id, stack_attributes) ⇒ TrueClass
Store stack attribute changes
112 113 114 115 116 117 118 119 120 |
# File 'lib/sfn/provider.rb', line 112 def (stack_id, stack_attributes) current_stacks = MultiJson.load(cached_stacks) cache.locked_action(:stacks_lock) do logger.info "Saving expanded stack attributes in cache (#{stack_id})" current_stacks[stack_id] = stack_attributes.merge('Cached' => Time.now.to_i) cache[:stacks].value = MultiJson.dump(current_stacks) end true end |
#service_for(service) ⇒ Miasma::Model
Build API connection for service type
216 217 218 |
# File 'lib/sfn/provider.rb', line 216 def service_for(service) connection.api_for(service) end |
#stack(stack_id) ⇒ Miasma::Orchestration::Stack, NilClass
103 104 105 |
# File 'lib/sfn/provider.rb', line 103 def stack(stack_id) stacks.get(stack_id) end |
#stacks ⇒ Miasma::Orchestration::Stacks
91 92 93 |
# File 'lib/sfn/provider.rb', line 91 def stacks connection.stacks.from_json(cached_stacks) end |
#update_stack_list! ⇒ TrueClass, FalseClass
Start async stack list update. Creates thread that loops every ‘self.stack_list_interval` seconds and refreshes stack list in cache
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/sfn/provider.rb', line 194 def update_stack_list! if(updater.nil? || !updater.alive?) self.updater = Thread.new{ loop do begin fetch_stacks sleep(stack_list_interval) rescue => e logger.error "Failure encountered on stack fetch: #{e.class} - #{e}" end end } true else false end end |