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



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

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

.check_if_logged_inObject



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/faastruby/local.rb', line 43

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)


28
29
30
31
# File 'lib/faastruby/local.rb', line 28

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



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

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

.functionsObject



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

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

.functions_dirObject



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

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

.get_crystal_versionObject



22
23
24
25
26
# File 'lib/faastruby/local.rb', line 22

def self.get_crystal_version
  debug "self.get_crystal_version"
  ver = `crystal -v|head -n1|cut -f2 -d' ' 2>/dev/null`&.chomp
  ver == '' ? CRYSTAL_LATEST : ver
end

.initial_compileObject



178
179
180
181
182
183
184
185
186
# File 'lib/faastruby/local.rb', line 178

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



196
197
198
199
200
201
202
# File 'lib/faastruby/local.rb', line 196

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



204
205
206
207
208
209
210
# File 'lib/faastruby/local.rb', line 204

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



212
213
214
215
216
217
218
# File 'lib/faastruby/local.rb', line 212

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



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

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

.opal_enabled?Boolean

Returns:

  • (Boolean)


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

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

.opal_js_destinationObject



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

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

.project_configObject



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

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

.public_dirObject



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

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

.root_toObject



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

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

.ruby_present_and_supported?Boolean

Returns:

  • (Boolean)


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

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



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

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

.secrets_for_function(function_name) ⇒ Object



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

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



143
144
145
146
147
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
# File 'lib/faastruby/local.rb', line 143

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



188
189
190
191
192
193
194
# File 'lib/faastruby/local.rb', line 188

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)


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

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

.workspaceObject



81
82
83
84
85
# File 'lib/faastruby/local.rb', line 81

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