terraspace 1.0.1 → 1.0.5

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
  SHA256:
3
- metadata.gz: b24e7a97ebf99ac393d03ef6ffec1381fae0508ae2c9f6bbaa9f0d7aad3139c3
4
- data.tar.gz: 5f553f4265a69128ef74dc7fdf22ea1dafbe0b2f73396fa4fa9b98cfcf24060a
3
+ metadata.gz: cfdfafd180a61f7e43131770457ffa446c8bae59d3db9e68c9b9a8930fa6ca88
4
+ data.tar.gz: 684480a5c4454ee457c5e236574ace9424a514d0822c2693190de41354aea40d
5
5
  SHA512:
6
- metadata.gz: 2cd672d6cd5bafdb40f2275a4ee34eab50ac3855b4df2ee535a89b3732f1fda7f07693da14bf2d9c82d49ae07871debdc115aca4e175068148917fa37b6694ec
7
- data.tar.gz: b3103984ef841b2082abf33fd84505db942e09b1a6a8bd0ca0a45774dbb018a31c202f1a3cf9fb0c7a87f1a51abf3825acbd12b325fa12264150d42deb323af8
6
+ metadata.gz: 73bef840c84345011a8246128537d81d76fee4c73215ac3856e43814e04304bfcf16d54213eee2fb940650f3fe4c13df249d1476805090cc0fbd7524f00fed00
7
+ data.tar.gz: a4b3f901aa19c01de17a059bd907197d4b2f8276a72de4ea29381ee803291ea9e4f33cc8c9667358247868297fb3b784dab1f0b127c7a04a98f37a56c4e2a773
data/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [1.0.5] - 2022-01-23
7
+ - [#194](https://github.com/boltops-tools/terraspace/pull/194) ability to allow and deny envs, regions, and stacks
8
+
9
+ ## [1.0.4] - 2022-01-21
10
+ - [#193](https://github.com/boltops-tools/terraspace/pull/193) improve all include_stacks and exclude_stacks option
11
+
12
+ ## [1.0.3] - 2022-01-20
13
+ - [#192](https://github.com/boltops-tools/terraspace/pull/192) run super-early boot hooks before dotenv load
14
+
15
+ ## [1.0.2] - 2022-01-17
16
+ - [#190](https://github.com/boltops-tools/terraspace/pull/190) update terraspace-bundler gem depedency to 0.5.0
17
+
6
18
  ## [1.0.1] - 2022-01-15
7
19
  - [#189](https://github.com/boltops-tools/terraspace/pull/189) dotenv support
8
20
 
@@ -0,0 +1,12 @@
1
+ class Terraspace::App::CallableOption
2
+ module Concern
3
+ def callable_option(options={})
4
+ callable_option = Terraspace::App::CallableOption.new(
5
+ config_name: options[:config_name],
6
+ config_value: options[:config_value],
7
+ passed_args: options[:passed_args],
8
+ )
9
+ callable_option.object
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,58 @@
1
+ # Class represents a terraspace option that is possibly callable. Examples:
2
+ #
3
+ # config.allow.envs
4
+ # config.allow.regions
5
+ # config.deny.envs
6
+ # config.deny.regions
7
+ # config.all.include_stacks
8
+ # config.all.exclude_stacks
9
+ #
10
+ # Abstraction is definitely obtuse. Using it to get rid of duplication.
11
+ #
12
+ class Terraspace::App
13
+ class CallableOption
14
+ include Terraspace::Util::Logging
15
+
16
+ def initialize(options={})
17
+ @options = options
18
+ # Example:
19
+ # config_name: config.allow.envs
20
+ # config_value: ["dev"]
21
+ # args: [@stack_name] # passed to object.call
22
+ @config_name = options[:config_name]
23
+ @config_value = options[:config_value]
24
+ @passed_args = options[:passed_args]
25
+ end
26
+
27
+ # Returns either an Array or nil
28
+ def object
29
+ case @config_value
30
+ when nil
31
+ return nil
32
+ when Array
33
+ return @config_value
34
+ when -> (c) { c.respond_to?(:public_instance_methods) && c.public_instance_methods.include?(:call) }
35
+ object= @config_value.new
36
+ when -> (c) { c.respond_to?(:call) }
37
+ object = @config_value
38
+ else
39
+ raise "Invalid option for #{@config_name}"
40
+ end
41
+
42
+ if object
43
+ result = @passed_args.empty? ? object.call : object.call(*@passed_args)
44
+ unless result.is_a?(Array) || result.is_a?(NilClass)
45
+ message = "ERROR: The #{@config_name} needs to return an Array or nil"
46
+ logger.info message.color(:yellow)
47
+ logger.info <<~EOL
48
+ The #{@config_name} when assigned a class, object, or proc must implement
49
+ the call method and return an Array or nil.
50
+ The current return value is a #{result.class}
51
+ EOL
52
+ raise message
53
+ end
54
+ end
55
+ result
56
+ end
57
+ end
58
+ end
@@ -12,16 +12,26 @@ module Terraspace
12
12
 
13
13
  def defaults
14
14
  config = ActiveSupport::OrderedOptions.new
15
+
15
16
  config.all = ActiveSupport::OrderedOptions.new
16
17
  config.all.concurrency = 5
17
18
  config.all.exit_on_fail = ActiveSupport::OrderedOptions.new
18
19
  config.all.exit_on_fail.down = true
19
20
  config.all.exit_on_fail.up = true
20
- config.all.ignore_stacks = nil
21
- config.all.include_stacks = nil
21
+
22
22
  config.allow = ActiveSupport::OrderedOptions.new
23
23
  config.allow.envs = nil
24
24
  config.allow.regions = nil
25
+ config.allow.stacks = nil
26
+ config.deny = ActiveSupport::OrderedOptions.new
27
+ config.deny.envs = nil
28
+ config.deny.regions = nil
29
+ config.deny.stacks = nil
30
+
31
+ config.all.exclude_stacks = nil
32
+ config.all.include_stacks = nil
33
+ config.all.consider_allow_deny_stacks = true
34
+
25
35
  config.auto_create_backend = true
26
36
  config.build = ActiveSupport::OrderedOptions.new
27
37
  config.build.cache_dir = ":CACHE_ROOT/:REGION/:ENV/:BUILD_DIR"
@@ -1,8 +1,8 @@
1
1
  module Terraspace
2
2
  module Booter
3
3
  def boot
4
- Dotenv.new.load!
5
4
  run_hooks
5
+ Dotenv.new.load!
6
6
  Terraspace::Bundle.require # load plugins
7
7
  load_plugin_default_configs
8
8
  Terraspace::App::Inits.run_all
@@ -0,0 +1,59 @@
1
+ class Terraspace::Builder::Allow
2
+ class Base
3
+ include Terraspace::App::CallableOption::Concern
4
+
5
+ def initialize(mod)
6
+ @mod = mod # Only Region subclass uses @mod but keeping interface same for Env for simplicity
7
+ @stack_name = mod.name
8
+ end
9
+
10
+ def check!
11
+ messages = []
12
+ unless allowed?
13
+ messages << message # message is interface method
14
+ end
15
+ unless messages.empty?
16
+ puts "ERROR: The configs do not allow this.".color(:red)
17
+ puts messages
18
+ exit 1
19
+ end
20
+ end
21
+
22
+ def allowed?
23
+ if allows.nil? && denys.nil?
24
+ true
25
+ elsif denys.nil?
26
+ allows.include?(check_value)
27
+ elsif allows.nil?
28
+ !denys.include?(check_value)
29
+ else
30
+ allows.include?(check_value) && !denys.include?(check_value)
31
+ end
32
+ end
33
+
34
+ def allows
35
+ callable_option(
36
+ config_name: "config.allow.#{config_name}",
37
+ config_value: config.dig(:allow, config_name),
38
+ passed_args: [@stack_name],
39
+ )
40
+ end
41
+
42
+ def denys
43
+ callable_option(
44
+ config_name: "config.deny.#{config_name}",
45
+ config_value: config.dig(:deny, config_name),
46
+ passed_args: [@stack_name],
47
+ )
48
+ end
49
+
50
+ private
51
+ def config
52
+ Terraspace.config
53
+ end
54
+
55
+ def config_name
56
+ self.class.to_s.split('::').last.underscore.pluralize.to_sym # ActiveSuport::HashWithIndifferentAccess#dig requires symbol
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ class Terraspace::Builder::Allow
2
+ class Env < Base
3
+ # interface method
4
+ def message
5
+ messages = []
6
+ messages << "This env is not allowed to be used: TS_ENV=#{Terraspace.env}"
7
+ messages << "Allow envs: #{allows.join(', ')}" if allows
8
+ messages << "Deny envs: #{denys.join(', ')}" if denys
9
+ messages.join("\n")
10
+ end
11
+
12
+ # interface method
13
+ def check_value
14
+ Terraspace.env
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ class Terraspace::Builder::Allow
2
+ class Region < Base
3
+ # interface method
4
+ def message
5
+ messages = []
6
+ word = config_name.to_s # IE: regions or locations
7
+ messages << "This #{word.singularize} is not allowed to be used: Detected current #{word.singularize}=#{current_region}"
8
+ messages << "Allow #{word}: #{allows.join(', ')}" if allows
9
+ messages << "Deny #{word}: #{denys.join(', ')}" if denys
10
+ messages.join("\n")
11
+ end
12
+
13
+ # interface method
14
+ def check_value
15
+ current_region
16
+ end
17
+
18
+ def current_region
19
+ expander = Terraspace::Compiler::Expander.autodetect(@mod).expander
20
+ expander.region
21
+ end
22
+
23
+ def config_name
24
+ if config.allow.locations || config.deny.locations
25
+ :locations # ActiveSuport::HashWithIndifferentAccess#dig requires symbol
26
+ else
27
+ super # :regions
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ class Terraspace::Builder::Allow
2
+ class Stack < Base
3
+ # interface method
4
+ def message
5
+ messages = []
6
+ messages << "This stack is not allowed to be used for TS_ENV=#{Terraspace.env}"
7
+ messages << "Allow stacks: #{allows.join(', ')}" if allows
8
+ messages << "Deny stacks: #{denys.join(', ')}" if denys
9
+ messages.join("\n")
10
+ end
11
+
12
+ # interface method
13
+ def check_value
14
+ @mod.name
15
+ end
16
+ end
17
+ end
@@ -5,39 +5,9 @@ class Terraspace::Builder
5
5
  end
6
6
 
7
7
  def check!
8
- messages = []
9
- unless env_allowed?
10
- messages << "This env is not allowed to be used: TS_ENV=#{Terraspace.env}"
11
- messages << "Allowed envs: #{config.allow.envs.join(', ')}"
12
- end
13
- unless region_allowed?
14
- messages << "This region is not allowed to be used: Detected current region=#{current_region}"
15
- messages << "Allowed regions: #{config.allow.regions.join(', ')}"
16
- end
17
- unless messages.empty?
18
- puts "ERROR: The configs do not allow this.".color(:red)
19
- puts messages
20
- exit 1
21
- end
22
- end
23
-
24
- def env_allowed?
25
- return true unless config.allow.envs
26
- config.allow.envs.include?(Terraspace.env)
27
- end
28
-
29
- def region_allowed?
30
- return true unless config.allow.regions
31
- config.allow.regions.include?(current_region)
32
- end
33
-
34
- def current_region
35
- expander = Terraspace::Compiler::Expander.autodetect(@mod).expander
36
- expander.region
37
- end
38
-
39
- def config
40
- Terraspace.config
8
+ Env.new(@mod).check!
9
+ Stack.new(@mod).check!
10
+ Region.new(@mod).check!
41
11
  end
42
12
  end
43
13
  end
@@ -1,28 +1,79 @@
1
1
  module Terraspace::Compiler
2
2
  class Select
3
+ include Terraspace::App::CallableOption::Concern
4
+ include Terraspace::Util::Logging
5
+
3
6
  def initialize(path)
4
7
  @path = path
5
8
  @stack_name = extract_stack_name(path)
6
9
  end
7
10
 
8
11
  def selected?
9
- all = Terraspace.config.all
10
- # Key difference between include_stacks vs all.include_stacks option is that
11
- # the option can be nil. The local variable is guaranteed to be an Array.
12
- # This simplifies the logic.
13
- include_stacks = all.include_stacks || []
14
- ignore_stacks = all.ignore_stacks || []
15
-
16
- if all.include_stacks.nil?
17
- !ignore_stacks.include?(@stack_name)
12
+ ignore_stacks_deprecation_warning
13
+ if include_stacks.nil? && exclude_stacks.nil?
14
+ true
15
+ elsif include_stacks.nil?
16
+ !exclude_stacks.include?(@stack_name)
17
+ elsif exclude_stacks.nil?
18
+ include_stacks.include?(@stack_name)
18
19
  else
19
- stacks = include_stacks - ignore_stacks
20
+ stacks = include_stacks - exclude_stacks
20
21
  stacks.include?(@stack_name)
21
22
  end
22
23
  end
23
24
 
25
+ def include_stacks
26
+ if config.all.include_stacks
27
+ config_name = "config.all.include_stacks"
28
+ config_value = config.dig(:all, :include_stacks)
29
+ elsif config.all.consider_allow_deny_stacks
30
+ config_name = "config.allow.stacks"
31
+ config_value = config.dig(:allow, :stacks)
32
+ else
33
+ return
34
+ end
35
+ callable_option(
36
+ config_name: config_name,
37
+ config_value: config_value,
38
+ passed_args: [@stack_name],
39
+ )
40
+ end
41
+
42
+ def exclude_stacks
43
+ if config.all.exclude_stacks
44
+ config_name = "config.all.exclude_stacks"
45
+ config_value = config.dig(:all, :exclude_stacks)
46
+ elsif config.all.consider_allow_deny_stacks
47
+ config_name = "config.deny.stacks"
48
+ config_value = config.dig(:deny, :stacks)
49
+ else
50
+ return
51
+ end
52
+ callable_option(
53
+ config_name: config_name,
54
+ config_value: config_value,
55
+ passed_args: [@stack_name],
56
+ )
57
+ end
58
+
59
+ private
60
+ def config
61
+ Terraspace.config
62
+ end
63
+
24
64
  def extract_stack_name(path)
25
65
  path.sub(%r{.*(app|vendor)/stacks/}, '')
26
66
  end
67
+
68
+ @@ignore_stacks_deprecation_warning = nil
69
+ def ignore_stacks_deprecation_warning
70
+ return unless config.all.ignore_stacks
71
+ return if @@ignore_stacks_deprecation_warning
72
+ puts <<~EOL.color(:yellow)
73
+ DEPRECATED: config.all.ignore_stacks
74
+ Instead use: config.all.exclude_stacks
75
+ EOL
76
+ @@ignore_stacks_deprecation_warning = true
77
+ end
27
78
  end
28
79
  end
@@ -1,3 +1,3 @@
1
1
  module Terraspace
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.5"
3
3
  end
data/terraspace.gemspec CHANGED
@@ -31,13 +31,13 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency "rainbow"
32
32
  spec.add_dependency "render_me_pretty"
33
33
  spec.add_dependency "rexml"
34
- spec.add_dependency "terraspace-bundler", "~> 0.4.4"
34
+ spec.add_dependency "terraspace-bundler", ">= 0.5.0"
35
35
  spec.add_dependency "thor"
36
36
  spec.add_dependency "tty-tree"
37
37
  spec.add_dependency "zeitwerk"
38
38
 
39
39
  # core baseline plugins
40
- spec.add_dependency "rspec-terraspace", "~> 0.3.0"
40
+ spec.add_dependency "rspec-terraspace", ">= 0.3.1"
41
41
 
42
42
  spec.add_development_dependency "bundler"
43
43
  spec.add_development_dependency "byebug"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terraspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-15 00:00:00.000000000 Z
11
+ date: 2022-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -196,16 +196,16 @@ dependencies:
196
196
  name: terraspace-bundler
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - "~>"
199
+ - - ">="
200
200
  - !ruby/object:Gem::Version
201
- version: 0.4.4
201
+ version: 0.5.0
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - "~>"
206
+ - - ">="
207
207
  - !ruby/object:Gem::Version
208
- version: 0.4.4
208
+ version: 0.5.0
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: thor
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -252,16 +252,16 @@ dependencies:
252
252
  name: rspec-terraspace
253
253
  requirement: !ruby/object:Gem::Requirement
254
254
  requirements:
255
- - - "~>"
255
+ - - ">="
256
256
  - !ruby/object:Gem::Version
257
- version: 0.3.0
257
+ version: 0.3.1
258
258
  type: :runtime
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
- - - "~>"
262
+ - - ">="
263
263
  - !ruby/object:Gem::Version
264
- version: 0.3.0
264
+ version: 0.3.1
265
265
  - !ruby/object:Gem::Dependency
266
266
  name: bundler
267
267
  requirement: !ruby/object:Gem::Requirement
@@ -478,12 +478,18 @@ files:
478
478
  - lib/terraspace/all/runner.rb
479
479
  - lib/terraspace/all/summary.rb
480
480
  - lib/terraspace/app.rb
481
+ - lib/terraspace/app/callable_option.rb
482
+ - lib/terraspace/app/callable_option/concern.rb
481
483
  - lib/terraspace/app/inits.rb
482
484
  - lib/terraspace/autodetect.rb
483
485
  - lib/terraspace/autoloader.rb
484
486
  - lib/terraspace/booter.rb
485
487
  - lib/terraspace/builder.rb
486
488
  - lib/terraspace/builder/allow.rb
489
+ - lib/terraspace/builder/allow/base.rb
490
+ - lib/terraspace/builder/allow/env.rb
491
+ - lib/terraspace/builder/allow/region.rb
492
+ - lib/terraspace/builder/allow/stack.rb
487
493
  - lib/terraspace/bundle.rb
488
494
  - lib/terraspace/cli.rb
489
495
  - lib/terraspace/cli/all.rb