humidifier 4.0.1 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,12 +15,12 @@ module Humidifier
15
15
  instance_variable_set(:"@#{property}", opts[property])
16
16
  end
17
17
 
18
- @type = opts.fetch(:type, 'String')
18
+ @type = opts.fetch(:type, "String")
19
19
  end
20
20
 
21
21
  # CFN stack syntax
22
22
  def to_cf
23
- { 'Type' => type }.tap do |cf|
23
+ { "Type" => type }.tap do |cf|
24
24
  PROPERTIES.each do |name, prop|
25
25
  value = public_send(prop)
26
26
  cf[name] = Serializer.dump(value) if value
@@ -18,12 +18,12 @@ module Humidifier
18
18
 
19
19
  # the link to the AWS docs
20
20
  def documentation
21
- spec['Documentation']
21
+ spec["Documentation"]
22
22
  end
23
23
 
24
24
  # true if this property is required by the resource
25
25
  def required?
26
- spec['Required']
26
+ spec["Required"]
27
27
  end
28
28
 
29
29
  # CFN stack syntax
@@ -34,7 +34,7 @@ module Humidifier
34
34
  # the type of update that occurs when this property is updated on its
35
35
  # associated resource
36
36
  def update_type
37
- spec['UpdateType']
37
+ spec["UpdateType"]
38
38
  end
39
39
 
40
40
  def valid?(value)
@@ -55,34 +55,70 @@ module Humidifier
55
55
 
56
56
  class BooleanProp < Prop
57
57
  allow_type TrueClass, FalseClass
58
+
59
+ def pretty_print(q)
60
+ q.text("(#{name}=boolean)")
61
+ end
58
62
  end
59
63
 
60
64
  class DoubleProp < Prop
61
65
  allow_type Integer, Float
66
+
67
+ def pretty_print(q)
68
+ q.text("(#{name}=double)")
69
+ end
62
70
  end
63
71
 
64
72
  class IntegerProp < Prop
65
73
  allow_type Integer
74
+
75
+ def pretty_print(q)
76
+ q.text("(#{name}=integer)")
77
+ end
66
78
  end
67
79
 
68
80
  class JsonProp < Prop
69
81
  allow_type Hash
82
+
83
+ def pretty_print(q)
84
+ q.text("(#{name}=json)")
85
+ end
70
86
  end
71
87
 
72
88
  class StringProp < Prop
73
89
  allow_type String
90
+
91
+ def pretty_print(q)
92
+ q.text("(#{name}=string)")
93
+ end
74
94
  end
75
95
 
76
96
  class TimestampProp < Prop
77
97
  allow_type Time, Date
98
+
99
+ def pretty_print(q)
100
+ q.text("(#{name}=timestamp)")
101
+ end
78
102
  end
79
103
 
80
104
  class ListProp < Prop
81
105
  attr_reader :subprop
82
106
 
83
- def initialize(key, spec = {}, substructs = {})
107
+ def initialize(key, spec = {}, subprop = nil)
84
108
  super(key, spec)
85
- @subprop = Props.singular_from(key, spec, substructs)
109
+ @subprop = subprop
110
+ end
111
+
112
+ def pretty_print(q)
113
+ q.group do
114
+ q.text("(#{name}=list")
115
+ q.nest(2) do
116
+ q.breakable
117
+ q.pp(subprop)
118
+ end
119
+ q.breakable("")
120
+ q.text(")")
121
+ end
86
122
  end
87
123
 
88
124
  def to_cf(list)
@@ -106,9 +142,21 @@ module Humidifier
106
142
  class MapProp < Prop
107
143
  attr_reader :subprop
108
144
 
109
- def initialize(key, spec = {}, substructs = {})
145
+ def initialize(key, spec = {}, subprop = nil)
110
146
  super(key, spec)
111
- @subprop = Props.singular_from(key, spec, substructs)
147
+ @subprop = subprop
148
+ end
149
+
150
+ def pretty_print(q)
151
+ q.group do
152
+ q.text("(#{name}=map")
153
+ q.nest(2) do
154
+ q.breakable
155
+ q.pp(subprop)
156
+ end
157
+ q.breakable("")
158
+ q.text(")")
159
+ end
112
160
  end
113
161
 
114
162
  def to_cf(map)
@@ -116,9 +164,9 @@ module Humidifier
116
164
  if map.respond_to?(:to_cf)
117
165
  map.to_cf
118
166
  else
119
- map.map do |subkey, subvalue|
167
+ map.to_h do |subkey, subvalue|
120
168
  [subkey, subprop.to_cf(subvalue).last]
121
- end.to_h
169
+ end
122
170
  end
123
171
 
124
172
  [key, cf_value]
@@ -134,9 +182,21 @@ module Humidifier
134
182
  class StructureProp < Prop
135
183
  attr_reader :subprops
136
184
 
137
- def initialize(key, spec = {}, substructs = {})
185
+ def initialize(key, spec = {}, subprops = {})
138
186
  super(key, spec)
139
- @subprops = subprops_from(substructs, spec['ItemType'] || spec['Type'])
187
+ @subprops = subprops
188
+ end
189
+
190
+ def pretty_print(q)
191
+ q.group do
192
+ q.text("(#{name}=structure")
193
+ q.nest(2) do
194
+ q.breakable
195
+ q.seplist(subprops.values) { |subprop| q.pp(subprop) }
196
+ end
197
+ q.breakable("")
198
+ q.text(")")
199
+ end
140
200
  end
141
201
 
142
202
  def to_cf(struct)
@@ -144,9 +204,9 @@ module Humidifier
144
204
  if struct.respond_to?(:to_cf)
145
205
  struct.to_cf
146
206
  else
147
- struct.map do |subkey, subvalue|
207
+ struct.to_h do |subkey, subvalue|
148
208
  subprops[subkey.to_s].to_cf(subvalue)
149
- end.to_h
209
+ end
150
210
  end
151
211
 
152
212
  [key, cf_value]
@@ -158,49 +218,11 @@ module Humidifier
158
218
 
159
219
  private
160
220
 
161
- def subprops_from(substructs, type)
162
- subprop_names = substructs.fetch(type, {}).fetch('Properties', {})
163
-
164
- subprop_names.each_with_object({}) do |(key, config), subprops|
165
- subprops[key.underscore] =
166
- if config['ItemType'] == type
167
- self
168
- else
169
- Props.from(key, config, substructs)
170
- end
171
- end
172
- end
173
-
174
221
  def valid_struct?(struct)
175
222
  struct.all? do |key, value|
176
223
  subprops.key?(key.to_s) && subprops[key.to_s].valid?(value)
177
224
  end
178
225
  end
179
226
  end
180
-
181
- class << self
182
- # builds the appropriate prop object from the given spec line
183
- def from(key, spec, substructs = {})
184
- case spec['Type']
185
- when 'List' then ListProp.new(key, spec, substructs)
186
- when 'Map' then MapProp.new(key, spec, substructs)
187
- else singular_from(key, spec, substructs)
188
- end
189
- end
190
-
191
- # builds a prop that is not a List or Map type
192
- # PrimitiveType is one of Boolean, Double, Integer, Json, String, or
193
- # Timestamp
194
- def singular_from(key, spec, substructs)
195
- primitive = spec['PrimitiveItemType'] || spec['PrimitiveType']
196
-
197
- if primitive && !%w[List Map].include?(primitive)
198
- primitive = 'Integer' if primitive == 'Long'
199
- const_get(:"#{primitive}Prop").new(key, spec)
200
- else
201
- StructureProp.new(key, spec, substructs)
202
- end
203
- end
204
- end
205
227
  end
206
228
  end
@@ -11,7 +11,7 @@ module Humidifier
11
11
 
12
12
  # Builds CFN syntax
13
13
  def to_cf
14
- { 'Ref' => Serializer.dump(reference) }
14
+ { "Ref" => Serializer.dump(reference) }
15
15
  end
16
16
  end
17
17
  end
@@ -45,8 +45,8 @@ module Humidifier
45
45
  end
46
46
 
47
47
  common_attributes.merge!(
48
- 'Type' => self.class.aws_name,
49
- 'Properties' => props_cf.to_h
48
+ "Type" => self.class.aws_name,
49
+ "Properties" => props_cf.to_h
50
50
  )
51
51
  end
52
52
 
@@ -114,7 +114,7 @@ module Humidifier
114
114
 
115
115
  def validate_property(property)
116
116
  unless self.class.prop?(property)
117
- raise ArgumentError, 'Attempting to set invalid property for ' \
117
+ raise ArgumentError, "Attempting to set invalid property for " \
118
118
  "#{self.class.name}: #{property}"
119
119
  end
120
120
 
@@ -7,7 +7,7 @@ module Humidifier
7
7
  # dumps the given object out to CFN syntax recursively
8
8
  def dump(node)
9
9
  case node
10
- when Hash then node.map { |key, value| [key, dump(value)] }.to_h
10
+ when Hash then node.to_h { |key, value| [key, dump(value)] }
11
11
  when Array then node.map { |value| dump(value) }
12
12
  when Ref, Fn then dump(node.to_cf)
13
13
  when Date then node.iso8601
@@ -14,8 +14,8 @@ module Humidifier
14
14
  super(
15
15
  "Cannot use a template > #{MAX_TEMPLATE_URL_SIZE} bytes " \
16
16
  "(currently #{bytesize} bytes), consider using nested stacks " \
17
- '(http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide' \
18
- '/aws-properties-stack.html)'
17
+ "(http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide" \
18
+ "/aws-properties-stack.html)"
19
19
  )
20
20
  end
21
21
  end
@@ -37,7 +37,7 @@ module Humidifier
37
37
  end
38
38
 
39
39
  # The AWS region, can be set through the environment, defaults to us-east-1
40
- AWS_REGION = ENV['AWS_REGION'] || 'us-east-1'
40
+ AWS_REGION = ENV.fetch("AWS_REGION", "us-east-1")
41
41
 
42
42
  # Lists of objects linked to the stack
43
43
  ENUMERABLE_RESOURCES =
@@ -184,7 +184,7 @@ module Humidifier
184
184
  perform_and_wait(:update, opts)
185
185
  end
186
186
 
187
- def upload # rubocop:disable Metrics/AbcSize
187
+ def upload
188
188
  raise NoResourcesError.new(self, :upload) unless resources.any?
189
189
 
190
190
  bucket = Humidifier.config.s3_bucket
@@ -231,9 +231,9 @@ module Humidifier
231
231
  next if resources.empty?
232
232
 
233
233
  list[name] =
234
- resources.map do |resource_name, resource|
234
+ resources.to_h do |resource_name, resource|
235
235
  [resource_name, resource.to_cf]
236
- end.to_h
236
+ end
237
237
  end
238
238
  end
239
239
 
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Humidifier
4
+ class Upgrade
5
+ PATH = -File.expand_path(File.join("..", "..", SPECIFICATION), __dir__)
6
+ URL = "https://docs.aws.amazon.com/AWSCloudFormation/latest" \
7
+ "/UserGuide/cfn-resource-specification.html"
8
+
9
+ def perform
10
+ require "net/http"
11
+ require "nokogiri"
12
+
13
+ response = Net::HTTP.get_response(uri).body
14
+ parsed = JSON.parse(response)
15
+
16
+ File.write(PATH, JSON.pretty_generate(parsed))
17
+ parsed["ResourceSpecificationVersion"]
18
+ end
19
+
20
+ def self.perform
21
+ new.perform
22
+ end
23
+
24
+ private
25
+
26
+ def page
27
+ Net::HTTP.get_response(URI.parse(URL)).body
28
+ end
29
+
30
+ def uri
31
+ Nokogiri::HTML(page).css("table tr").detect do |tr|
32
+ name = tr.at_css("td:first-child p")
33
+ next if !name || name.text.strip != "US East (N. Virginia)"
34
+
35
+ break URI.parse(tr.at_css("td:nth-child(3) p a").attr("href"))
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Humidifier
4
- VERSION = '4.0.1'
4
+ VERSION = "4.2.0"
5
5
  end
data/lib/humidifier.rb CHANGED
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'date'
4
- require 'json'
5
- require 'pathname'
6
- require 'yaml'
3
+ require "date"
4
+ require "json"
5
+ require "pathname"
6
+ require "yaml"
7
7
 
8
- require 'aws-sdk-cloudformation'
9
- require 'aws-sdk-s3'
10
- require 'fast_underscore'
11
- require 'thor'
12
- require 'thor/hollaback'
8
+ require "aws-sdk-cloudformation"
9
+ require "aws-sdk-s3"
10
+ require "fast_underscore"
11
+ require "thor"
12
+ require "thor/hollaback"
13
13
 
14
14
  # Hook into the string extension and ensure it works for certain AWS acronyms
15
15
  String.prepend(
@@ -22,6 +22,9 @@ String.prepend(
22
22
 
23
23
  # container module for all gem classes
24
24
  module Humidifier
25
+ # The file name of the specification for consistency.
26
+ SPECIFICATION = "CloudFormationResourceSpecification.json"
27
+
25
28
  # A parent class for all Humidifier errors for easier rescuing.
26
29
  class Error < StandardError; end
27
30
 
@@ -58,29 +61,30 @@ module Humidifier
58
61
 
59
62
  # a frozen hash of the given names mapped to their underscored version
60
63
  def underscore(names)
61
- names.map { |name| [name, name.underscore.to_sym] }.to_h.freeze
64
+ names.to_h { |name| [name, name.underscore.to_sym] }.freeze
62
65
  end
63
66
  end
64
67
  end
65
68
 
66
- require 'humidifier/fn'
67
- require 'humidifier/ref'
68
- require 'humidifier/props'
69
-
70
- require 'humidifier/cli'
71
- require 'humidifier/condition'
72
- require 'humidifier/directory'
73
- require 'humidifier/loader'
74
- require 'humidifier/mapping'
75
- require 'humidifier/output'
76
- require 'humidifier/parameter'
77
- require 'humidifier/resource'
78
- require 'humidifier/serializer'
79
- require 'humidifier/stack'
80
- require 'humidifier/version'
81
-
82
- require 'humidifier/config'
83
- require 'humidifier/config/mapper'
84
- require 'humidifier/config/mapping'
69
+ require "humidifier/fn"
70
+ require "humidifier/ref"
71
+ require "humidifier/props"
72
+
73
+ require "humidifier/cli"
74
+ require "humidifier/condition"
75
+ require "humidifier/directory"
76
+ require "humidifier/loader"
77
+ require "humidifier/mapping"
78
+ require "humidifier/output"
79
+ require "humidifier/parameter"
80
+ require "humidifier/resource"
81
+ require "humidifier/serializer"
82
+ require "humidifier/stack"
83
+ require "humidifier/upgrade"
84
+ require "humidifier/version"
85
+
86
+ require "humidifier/config"
87
+ require "humidifier/config/mapper"
88
+ require "humidifier/config/mapping"
85
89
 
86
90
  Humidifier::Loader.load
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: humidifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Kevin Deisz
8
- autorequire:
9
- bindir: bin
7
+ - Kevin Newton
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-14 00:00:00.000000000 Z
11
+ date: 2022-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-cloudformation
@@ -53,75 +53,75 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.3'
55
55
  - !ruby/object:Gem::Dependency
56
- name: thor
56
+ name: nokogiri
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.20'
61
+ version: '1.10'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.20'
68
+ version: '1.10'
69
69
  - !ruby/object:Gem::Dependency
70
- name: thor-hollaback
70
+ name: thor
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0.1'
75
+ version: '1.0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0.1'
82
+ version: '1.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: bundler
84
+ name: thor-hollaback
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2.0'
90
- type: :development
89
+ version: '0.2'
90
+ type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '2.0'
96
+ version: '0.2'
97
97
  - !ruby/object:Gem::Dependency
98
- name: minitest
98
+ name: bundler
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '5.11'
103
+ version: '2.0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '5.11'
110
+ version: '2.0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: nokogiri
112
+ name: minitest
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '1.10'
117
+ version: '5.13'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '1.10'
124
+ version: '5.13'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rake
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '0.74'
145
+ version: '1.24'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '0.74'
152
+ version: '1.24'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: simplecov
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -181,14 +181,27 @@ dependencies:
181
181
  description: Programmatically generate and manage AWS CloudFormation templates, stacks,
182
182
  and change sets.
183
183
  email:
184
- - kevin.deisz@gmail.com
185
- executables: []
184
+ - kddnewton@gmail.com
185
+ executables:
186
+ - humidifier
186
187
  extensions: []
187
188
  extra_rdoc_files: []
188
189
  files:
190
+ - ".github/dependabot.yml"
191
+ - ".github/workflows/main.yml"
192
+ - ".gitignore"
193
+ - ".rubocop.yml"
194
+ - ".yardopts"
195
+ - CHANGELOG.md
196
+ - CODE_OF_CONDUCT.md
189
197
  - CloudFormationResourceSpecification.json
198
+ - Gemfile
199
+ - Gemfile.lock
190
200
  - LICENSE
191
201
  - README.md
202
+ - Rakefile
203
+ - exe/humidifier
204
+ - humidifier.gemspec
192
205
  - lib/humidifier.rb
193
206
  - lib/humidifier/cli.rb
194
207
  - lib/humidifier/condition.rb
@@ -206,12 +219,17 @@ files:
206
219
  - lib/humidifier/resource.rb
207
220
  - lib/humidifier/serializer.rb
208
221
  - lib/humidifier/stack.rb
222
+ - lib/humidifier/upgrade.rb
209
223
  - lib/humidifier/version.rb
210
- homepage: https://github.com/kddeisz/humidifier
224
+ homepage: https://github.com/kddnewton/humidifier
211
225
  licenses:
212
226
  - MIT
213
- metadata: {}
214
- post_install_message:
227
+ metadata:
228
+ bug_tracker_uri: https://github.com/kddnewton/humidifier/issues
229
+ changelog_uri: https://github.com/kddnewton/humidifier/blob/v4.2.0/CHANGELOG.md
230
+ source_code_uri: https://github.com/kddnewton/humidifier
231
+ rubygems_mfa_required: 'true'
232
+ post_install_message:
215
233
  rdoc_options: []
216
234
  require_paths:
217
235
  - lib
@@ -219,15 +237,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
219
237
  requirements:
220
238
  - - ">="
221
239
  - !ruby/object:Gem::Version
222
- version: '2.4'
240
+ version: '0'
223
241
  required_rubygems_version: !ruby/object:Gem::Requirement
224
242
  requirements:
225
243
  - - ">="
226
244
  - !ruby/object:Gem::Version
227
245
  version: '0'
228
246
  requirements: []
229
- rubygems_version: 3.0.6
230
- signing_key:
247
+ rubygems_version: 3.3.3
248
+ signing_key:
231
249
  specification_version: 4
232
250
  summary: CloudFormation made easy
233
251
  test_files: []