Module: FaaStRuby::Local

Extended by:
Logger
Defined in:
lib/faastruby/local.rb,
lib/faastruby/local/logger.rb,
lib/faastruby/server/local.rb,
lib/faastruby/local/functions.rb,
lib/faastruby/local/listeners.rb,
lib/faastruby/local/processors.rb,
lib/faastruby/local/static_files.rb,
lib/faastruby/local/functions/ruby.rb,
lib/faastruby/local/processors/opal.rb,
lib/faastruby/local/functions/crystal.rb,
lib/faastruby/local/functions/function.rb,
lib/faastruby/local/listeners/listener.rb,
lib/faastruby/local/processors/function.rb,
lib/faastruby/local/processors/processor.rb,
lib/faastruby/local/processors/static_file.rb,
lib/faastruby/local/static_files/static_file.rb

Defined Under Namespace

Modules: Logger Classes: CrystalFunction, Function, FunctionProcessor, Listener, ListenerEvent, MissingConfigurationFileError, OpalProcessor, Processor, RubyFunction, StaticFile, StaticFileProcessor

Constant Summary collapse

DEBUG =
ENV['DEBUG']
CRYSTAL_ENABLED =
crystal_present_and_supported?
RUBY_ENABLED =
ruby_present_and_supported?
SERVER_ROOT =
Dir.pwd
PROJECT_YAML_FILE =
"#{SERVER_ROOT}/project.yml"
SECRETS_YAML_FILE =
"#{SERVER_ROOT}/secrets.yml"
DEPLOY_ENVIRONMENT =
ENV['DEPLOY_ENVIRONMENT'] || 'stage'
SYNC_ENABLED =
ENV['SYNC'] && check_if_logged_in
CRYSTAL_VERSION =
get_crystal_version.freeze
DEFAULT_CRYSTAL_RUNTIME =
"crystal:#{CRYSTAL_VERSION}".freeze
DEFAULT_RUBY_RUNTIME =
"ruby:#{CURRENT_MINOR_RUBY}".freeze
FUNCTIONS_EVENT_QUEUE =
Queue.new
PUBLIC_EVENT_QUEUE =
Queue.new
OPAL_EVENT_QUEUE =
Queue.new
WORKSPACE_BASE_HOST =
ENV['FAASTRUBY_WORKSPACE_BASE_HOST'] || 'faast.cloud'
URL_PROTOCOL =
ENV['FAASTRUBY_URL_PROTOCOL'] || 'https'
STDOUT_MUTEX =
Mutex.new

Class Method Summary collapse

Methods included from Logger

debug, puts, puts

Class Method Details

.catch_allObject



111
112
113
114
# File 'lib/faastruby/local.rb', line 111

def self.catch_all
  debug "self.catch_all"
  project_config['catch_all'] || 'catch-all'
end

.check_if_logged_inObject



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/faastruby/local.rb', line 48

def self.check_if_logged_in
  creds_file = File.expand_path("~/.faastruby/credentials.yml")
  yaml = YAML.load(File.read(creds_file)) rescue {}
  unless yaml['credentials'] && yaml['credentials']['email']
    STDOUT.puts "@@@ WARNING @@@ | You need to be logged in to use FaaStRuby Local with sync mode.".red
    STDOUT.puts "@@@ WARNING @@@ | To login, run: faastruby login".red
    STDOUT.puts "@@@ WARNING @@@ | Sync mode is *NOT* enabled!".red
    STDOUT.puts "---".red
    return false
  end
  return true
end

.crystal_present_and_supported?Boolean

Returns:

  • (Boolean)


33
34
35
36
# File 'lib/faastruby/local.rb', line 33

def self.crystal_present_and_supported?
  debug "self.crystal_present_and_supported?"
  system("which crystal >/dev/null") && version_match?(SUPPORTED_CRYSTAL, get_crystal_version)
end

.deploy_environment_secretsObject



126
127
128
129
# File 'lib/faastruby/local.rb', line 126

def self.deploy_environment_secrets
  debug "self.deploy_environment_secrets"
  secrets[DEPLOY_ENVIRONMENT] || {}
end

.functionsObject



116
117
118
119
# File 'lib/faastruby/local.rb', line 116

def self.functions
  debug "self.functions"
  @@functions ||= []
end

.functions_dirObject



96
97
98
99
# File 'lib/faastruby/local.rb', line 96

def self.functions_dir
  debug "self.functions_dir"
  "#{SERVER_ROOT}/#{project_config['functions_dir'] || 'functions'}"
end

.get_crystal_versionObject



22
23
24
25
26
27
28
29
30
31
# File 'lib/faastruby/local.rb', line 22

def self.get_crystal_version
  debug "self.get_crystal_version"
  major, minor, patch = `crystal -v|head -n1|cut -f2 -d' ' 2>/dev/null`&.chomp&.split('.')
  ver = "#{major}.#{minor}"
  if ver == '.' || ver == ''
    CRYSTAL_LATEST
  else
    ver
  end
end

.initial_compileObject



183
184
185
186
187
188
189
190
191
# File 'lib/faastruby/local.rb', line 183

def self.initial_compile
  debug __method__
  Thread.new do
    sleep 1
    crystal_functions = @@functions.map{|f| f if f.language == "crystal"}.compact
    puts "Triggering 'compile' on Crystal functions." if crystal_functions.any?
    crystal_functions.each {|f| FileUtils.touch("#{f.absolute_folder}/faastruby.yml")}
  end
end

.listen_on_functions_dirObject



201
202
203
204
205
206
207
# File 'lib/faastruby/local.rb', line 201

def self.listen_on_functions_dir
  debug "self.listen_on_functions_dir"
  debug "Listening for changes in '#{functions_dir}'"
  listener = Listener.new(directory: functions_dir, queue: FUNCTIONS_EVENT_QUEUE)
  listener.start
  Local::Listener.functions_listener << listener
end

.listen_on_opal_dirObject



209
210
211
212
213
214
215
# File 'lib/faastruby/local.rb', line 209

def self.listen_on_opal_dir
  debug "self.listen_on_opal_dir"
  debug "Listening for changes in '#{opal_dir}'"
  listener = Listener.new(directory: opal_dir, queue: OPAL_EVENT_QUEUE)
  listener.start
  Local::Listener.opal_listener << listener
end

.listen_on_public_dirObject



217
218
219
220
221
222
223
# File 'lib/faastruby/local.rb', line 217

def self.listen_on_public_dir
  debug "self.listen_on_public_dir"
  debug "Listening for changes in '#{public_dir}'"
  listener = Listener.new(directory: public_dir, queue: PUBLIC_EVENT_QUEUE)
  listener.start
  Local::Listener.public_listener << listener
end

.opal_dirObject



140
141
142
# File 'lib/faastruby/local.rb', line 140

def self.opal_dir
  "#{SERVER_ROOT}/#{project_config['opal_dir']}"
end

.opal_enabled?Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/faastruby/local.rb', line 136

def self.opal_enabled?
  !project_config['opal_dir'].nil?
end

.opal_js_destinationObject



144
145
146
# File 'lib/faastruby/local.rb', line 144

def self.opal_js_destination
  project_config['opal_js_destination'] || "#{public_dir}/assets/javascripts"
end

.project_configObject



92
93
94
95
# File 'lib/faastruby/local.rb', line 92

def self.project_config
  debug "self.project_config"
  yaml = YAML.load(File.read(PROJECT_YAML_FILE))['project']
end

.public_dirObject



101
102
103
104
# File 'lib/faastruby/local.rb', line 101

def self.public_dir
  debug "self.public_dir"
  "#{SERVER_ROOT}/#{project_config['public_dir'] || 'public'}"
end

.root_toObject



106
107
108
109
# File 'lib/faastruby/local.rb', line 106

def self.root_to
  debug "self.root_to"
  project_config['root_to'] || 'root'
end

.ruby_present_and_supported?Boolean

Returns:

  • (Boolean)


38
39
40
41
# File 'lib/faastruby/local.rb', line 38

def self.ruby_present_and_supported?
  debug "self.ruby_present_and_supported?"
  system("which ruby >/dev/null") && version_match?(SUPPORTED_RUBY, RUBY_VERSION)
end

.secretsObject



131
132
133
134
# File 'lib/faastruby/local.rb', line 131

def self.secrets
  debug "self.secrets"
  YAML.load(File.read(SECRETS_YAML_FILE))['secrets'] || {}
end

.secrets_for_function(function_name) ⇒ Object



121
122
123
124
# File 'lib/faastruby/local.rb', line 121

def self.secrets_for_function(function_name)
  debug "self.secrets_for_function(#{function_name.inspect})"
  deploy_environment_secrets[function_name] || {}
end

.start!(sync: false, deploy_env: 'stage', debug: false) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/faastruby/local.rb', line 148

def self.start!
  Listen::Adapter::Linux::DEFAULTS[:events] << :modify
  debug "self.start!"
  sync_mode_enabled if SYNC_ENABLED
  @@functions = Function.find_all_in(functions_dir)
  ruby_functions = @@functions.map{|f| f.name if f.language == "ruby"}.compact
  crystal_functions = @@functions.map{|f| f.name if f.language == "crystal"}.compact
  puts "Detecting existing functions."
  puts "Ruby functions: #{ruby_functions.inspect}"
  puts "Crystal functions: #{crystal_functions.inspect}"

  listen_on_functions_dir
  if opal_enabled?
    puts "Opal Ruby files will be auto-compiled to Javascript and added to '#{opal_js_destination}'."
    FileUtils.mkdir_p(Local.opal_dir)
    listen_on_opal_dir
  end
  listen_on_public_dir if SYNC_ENABLED

  FunctionProcessor.new(FUNCTIONS_EVENT_QUEUE).start
  OpalProcessor.new(OPAL_EVENT_QUEUE).start if opal_enabled?
  StaticFileProcessor.new(PUBLIC_EVENT_QUEUE).start if SYNC_ENABLED

  # initial_compile
  puts "Listening for changes."
  puts "faastRuby Local is ready at http://localhost:#{ENV['SERVER_PORT']}"
  puts "Your cloud workspace address is #{URL_PROTOCOL}://#{workspace}.#{FaaStRuby.region}.#{WORKSPACE_BASE_HOST}" if SYNC_ENABLED
  sleep
ensure
  puts "Stopping Watchdog..."
  Local::Listener.functions_listener.each(&:stop)
  Local::Listener.public_listener.each(&:stop)
  Local::Listener.opal_listener.each(&:stop)
end

.sync_mode_enabledObject



193
194
195
196
197
198
199
# File 'lib/faastruby/local.rb', line 193

def self.sync_mode_enabled
  debug __method__
  puts "Sync mode enabled."
  puts "Your local environment will be synced to #{URL_PROTOCOL}://#{workspace}.#{FaaStRuby.region}.#{WORKSPACE_BASE_HOST}"
  system("faastruby deploy --env #{DEPLOY_ENVIRONMENT}")
  true
end

.version_match?(supported, current) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
46
# File 'lib/faastruby/local.rb', line 43

def self.version_match?(supported, current)
  supported.each {|supported_version| return true if Gem::Dependency.new('', supported_version).match?('', current)}
  return false
end

.workspaceObject



86
87
88
89
90
# File 'lib/faastruby/local.rb', line 86

def self.workspace
  debug "self.workspace"
  return "#{project_config['name']}-#{DEPLOY_ENVIRONMENT}-#{project_config['identifier']}" if project_config['identifier']
  "#{project_config['name']}-#{DEPLOY_ENVIRONMENT}"
end