Class: Jets::Application

Inherits:
Object
  • Object
show all
Extended by:
Memoist
Includes:
Middleware
Defined in:
lib/jets/application.rb

Defined Under Namespace

Modules: Middleware

Constant Summary collapse

ENV_MAP =

Use the shorter name in stack names, but use the full name when it comes to checking for the env.

Example:

Jets.env: 'development'
Jets.config.project_namespace: 'demo-dev'
{
  development: 'dev',
  production: 'prod',
  staging: 'stag',
}

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Middleware

#assemble_app, #call

Class Method Details

.default_iam_policyObject



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/jets/application.rb', line 137

def self.default_iam_policy
  project_namespace = Jets.project_namespace
  logs = {
    action: ["logs:*"],
    effect: "Allow",
    resource: "arn:aws:logs:#{Jets.aws.region}:#{Jets.aws.account}:log-group:/aws/lambda/#{project_namespace}-*",
  }
  s3_bucket = Jets.aws.s3_bucket
  s3_readonly = {
    action: ["s3:Get*", "s3:List*"],
    effect: "Allow",
    resource: "arn:aws:s3:::#{s3_bucket}*",
  }
  s3_bucket = {
    action: ["s3:ListAllMyBuckets", "s3:HeadBucket"],
    effect: "Allow",
    resource: "arn:aws:s3:::*", # scoped to all buckets
  }
  policies = [logs, s3_readonly, s3_bucket]

  if Jets::Stack.has_resources?
    cloudformation = {
      action: ["cloudformation:DescribeStacks"],
      effect: "Allow",
      resource: "arn:aws:cloudformation:#{Jets.aws.region}:#{Jets.aws.account}:stack/#{project_namespace}*",
    }
    policies << cloudformation
  end
  policies
end

Instance Method Details

#awsObject



206
207
208
# File 'lib/jets/application.rb', line 206

def aws
  Jets::AwsInfo.new
end

#configObject

Default config



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/jets/application.rb', line 25

def config
  config = ActiveSupport::OrderedOptions.new

  config.prewarm = ActiveSupport::OrderedOptions.new
  config.prewarm.enable = true
  config.prewarm.rate = '30 minutes'
  config.prewarm.concurrency = 2
  config.prewarm.public_ratio = 3

  config.lambdagems = ActiveSupport::OrderedOptions.new
  config.lambdagems.sources = [
    'https://gems.lambdagems.com'
  ]

  config.inflections = ActiveSupport::OrderedOptions.new
  config.inflections.irregular = {}

  config.assets = ActiveSupport::OrderedOptions.new
  config.assets.folders = %w[public]
  config.assets.base_url = nil # IE: https://cloudfront.com/my/base/path
  config.assets.max_age = 3600
  config.assets.cache_control = nil # IE: public, max-age=3600 , max_age is a shorter way to set cache_control.

  config.ruby = ActiveSupport::OrderedOptions.new
  config.ruby.lazy_load = true # also set in config/environments files

  config
end

#configure(&block) ⇒ Object



9
10
11
# File 'lib/jets/application.rb', line 9

def configure(&block)
  instance_eval(&block) if block
end

#internal_autoload_pathsObject



63
64
65
66
67
68
69
70
71
# File 'lib/jets/application.rb', line 63

def internal_autoload_paths
  internal = File.expand_path("../internal", __FILE__)
  paths = %w[
    app/controllers
    app/models
    app/jobs
  ]
  paths.map { |path| "#{internal}/#{path}" }
end

#load_configsObject



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/jets/application.rb', line 73

def load_configs
  # The Jets default/application.rb is loaded.
  require File.expand_path("../default/application.rb", __FILE__)
  # Then project config/application.rb is loaded.
  app_config = "#{Jets.root}config/application.rb"
  require app_config if File.exist?(app_config)
  # Normalize config and setup some shortcuts
  set_aliases!
  normalize_env_vars!
  load_db_config
  load_environments_config
end

#load_db_configObject



180
181
182
183
184
185
186
187
188
189
190
# File 'lib/jets/application.rb', line 180

def load_db_config
  config.database = {}

  Jets::Dotenv.load!
  database_yml = "#{Jets.root}config/database.yml"
  if File.exist?(database_yml)
    text = Jets::Erb.result(database_yml)
    db_config = YAML.load(text)
    config.database = db_config
  end
end

#load_environments_configObject



86
87
88
89
90
91
92
# File 'lib/jets/application.rb', line 86

def load_environments_config
  env_file = "#{Jets.root}config/environments/#{Jets.env}.rb"
  if File.exist?(env_file)
    code = IO.read(env_file)
    instance_eval(code)
  end
end

#load_inflectionsObject



20
21
22
# File 'lib/jets/application.rb', line 20

def load_inflections
  Jets::Inflections.load!
end

#load_routesObject



201
202
203
204
# File 'lib/jets/application.rb', line 201

def load_routes
  routes_file = "#{Jets.root}config/routes.rb"
  require routes_file if File.exist?(routes_file)
end

#normalize_env_vars!Object

It is pretty easy to attempt to set environment variables without the correct AWS Environment.Variables path struture. Auto-fix it for convenience.



171
172
173
174
175
176
177
178
# File 'lib/jets/application.rb', line 171

def normalize_env_vars!
  environment = config.function.environment
  if environment and !environment.to_h.key?(:variables)
    config.function.environment = {
      variables: environment.to_h
    }
  end
end

#reload_iam_policy!Object

After the mimimal template gets build, we need to reload it for the full stack creation. This is confusing to follow. Think we need to clean up the Jets.application singleton and make it more explicit?



131
132
133
134
135
# File 'lib/jets/application.rb', line 131

def reload_iam_policy!
  config.iam_policy = nil
  config.managed_policy_definitions = nil
  set_iam_policy
end

#routesObject

Naming it routes because config/routes.rb requires

Jets.application.routes.draw do

for scaffolding to work.



197
198
199
# File 'lib/jets/application.rb', line 197

def routes
  @router ||= Jets::Router.new
end

#set_aliases!Object



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/jets/application.rb', line 106

def set_aliases!
  # env_extra can be also be set with JETS_ENV_EXTRA.
  # JETS_ENV_EXTRA higher precedence than config.env_extra
  config.env_extra = ENV['JETS_ENV_EXTRA'] if ENV['JETS_ENV_EXTRA']
  # IE: With env_extra: project-dev-1
  #     Without env_extra: project-dev
  config.short_env = ENV_MAP[Jets.env.to_sym] || Jets.env
  # table_namespace does not have the env_extra, more common case desired.
  config.table_namespace = [config.project_name, config.short_env].compact.join('-')

  config.project_namespace = Jets.project_namespace

  # Must set default iam_policy here instead of `def config` because we  project_namespace
  # must have been set and if we call it from `def config` we get an infinite loop
  set_iam_policy
end

#set_iam_policyObject



123
124
125
126
# File 'lib/jets/application.rb', line 123

def set_iam_policy
  config.iam_policy ||= self.class.default_iam_policy
  config.managed_policy_definitions ||= [] # default empty
end

#setup!Object



13
14
15
16
17
18
# File 'lib/jets/application.rb', line 13

def setup!
  load_configs # load config object so following methods can use it
  load_inflections
  setup_auto_load_paths
  load_routes
end

#setup_auto_load_pathsObject



55
56
57
58
59
60
61
# File 'lib/jets/application.rb', line 55

def setup_auto_load_paths
  autoload_paths = config.autoload_paths + config.extra_autoload_paths
  autoload_paths = autoload_paths.uniq.map { |p| "#{Jets.root}#{p}" }
  # internal_autoload_paths are last
  autoload_paths += internal_autoload_paths
  ActiveSupport::Dependencies.autoload_paths += autoload_paths
end