stemcell 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +6 -0
  3. data/Gemfile.lock +18 -0
  4. data/lib/stemcell/command_line.rb +2 -2
  5. data/lib/stemcell/errors.rb +3 -2
  6. data/lib/stemcell/metadata_source/chef_repository.rb +55 -0
  7. data/lib/stemcell/metadata_source/configuration.rb +77 -0
  8. data/lib/stemcell/metadata_source.rb +51 -98
  9. data/lib/stemcell/version.rb +1 -1
  10. data/lib/stemcell.rb +0 -2
  11. data/spec/fixtures/chef_repo/roles/unit-inherit-base.rb +20 -0
  12. data/spec/fixtures/chef_repo/roles/unit-inherit-both.rb +36 -0
  13. data/spec/fixtures/chef_repo/roles/unit-inherit-default.rb +21 -0
  14. data/spec/fixtures/chef_repo/roles/unit-inherit-none.rb +6 -0
  15. data/spec/fixtures/chef_repo/roles/unit-inherit-override.rb +21 -0
  16. data/spec/fixtures/chef_repo/roles/unit-simple-both.rb +29 -0
  17. data/spec/fixtures/chef_repo/roles/unit-simple-default.rb +16 -0
  18. data/spec/fixtures/chef_repo/roles/unit-simple-none.rb +2 -0
  19. data/spec/fixtures/chef_repo/roles/unit-simple-override.rb +16 -0
  20. data/spec/fixtures/chef_repo/roles-expected-metadata/unit-inherit-both.json +16 -0
  21. data/spec/fixtures/chef_repo/roles-expected-metadata/unit-inherit-default.json +14 -0
  22. data/spec/fixtures/chef_repo/roles-expected-metadata/unit-inherit-none.json +11 -0
  23. data/spec/fixtures/chef_repo/roles-expected-metadata/unit-inherit-override.json +14 -0
  24. data/spec/fixtures/chef_repo/roles-expected-metadata/unit-simple-both.json +13 -0
  25. data/spec/fixtures/chef_repo/roles-expected-metadata/unit-simple-default.json +11 -0
  26. data/spec/fixtures/chef_repo/roles-expected-metadata/unit-simple-override.json +11 -0
  27. data/spec/fixtures/chef_repo/stemcell-azs-missing.json +10 -0
  28. data/spec/fixtures/chef_repo/stemcell-backing-store-empty.json +9 -0
  29. data/spec/fixtures/chef_repo/stemcell-backing-store-missing.json +8 -0
  30. data/spec/fixtures/chef_repo/stemcell-defaults-missing.json +10 -0
  31. data/spec/fixtures/chef_repo/stemcell.json +13 -0
  32. data/spec/lib/stemcell/metadata_source/chef_repository_spec.rb +107 -0
  33. data/spec/lib/stemcell/metadata_source/configuration_spec.rb +117 -0
  34. data/spec/lib/stemcell/metadata_source_spec.rb +250 -0
  35. data/spec/spec_helper.rb +13 -0
  36. data/spec/support/fixture_helper.rb +14 -0
  37. metadata +60 -24
  38. data/lib/stemcell/utility/deep_merge.rb +0 -13
  39. data/lib/stemcell/utility.rb +0 -1
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YWQxNmQ0NDdkNGMzZmRlMzVhOTMzNzJjODFlMDIyZTFkZjUyY2RiNA==
5
+ data.tar.gz: !binary |-
6
+ Y2RmNDdjNDZjNzIxNDIyNWE1MWNlMDZmZWM3ZWYxZjA2NzVjYWI0Nw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NmRjOGQwOGVhMjFiZDZiNDVhZWQ3OGE2YTczOTU5MjhhOWNmZTdkYTIzYzYw
10
+ OGJmZGExMzM2YmRhMWQ0YTVjZTAzYjJmOTA2N2U2YTEyMGE1OTBmNGM1ODUz
11
+ YjU4N2EyMzFjNmE4ZDNjYTMwYTg1NGQ5MWNiOTRlNzUwZGQ0MTA=
12
+ data.tar.gz: !binary |-
13
+ OGY3NzRhYjY0ZTc1OGI2N2RmN2FlZWEwMGUxYmY1NjU0YWZmMjc0N2YyYWRi
14
+ ZjZmZTc1NGQ2OTRkYWNmMjUxM2JiOWRmZGRkNzg2ZGNlN2JkOTg5MjAyYzA4
15
+ MDI5YzQ4NzgxYmEzNmJlNjAzN2ZmNTExMTM1N2E5ZTU5NmQ3NDc=
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in stemcell.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem 'rspec', '~> 2.14.1'
8
+ gem 'rspec-instafail', '~> 0.2.4'
9
+ gem 'simplecov', :require => false
10
+ end
data/Gemfile.lock CHANGED
@@ -34,6 +34,7 @@ GEM
34
34
  rest-client (>= 1.0.4, < 1.7.0)
35
35
  yajl-ruby (~> 1.1)
36
36
  colored (1.2)
37
+ diff-lcs (1.2.5)
37
38
  erubis (2.7.0)
38
39
  highline (1.6.19)
39
40
  ipaddress (0.8.0)
@@ -45,6 +46,7 @@ GEM
45
46
  mixlib-config (1.1.2)
46
47
  mixlib-log (1.6.0)
47
48
  mixlib-shellout (1.1.0)
49
+ multi_json (1.8.2)
48
50
  net-ssh (2.7.0)
49
51
  net-ssh-gateway (1.2.0)
50
52
  net-ssh (>= 2.6.5)
@@ -62,6 +64,19 @@ GEM
62
64
  yajl-ruby
63
65
  rest-client (1.6.7)
64
66
  mime-types (>= 1.16)
67
+ rspec (2.14.1)
68
+ rspec-core (~> 2.14.0)
69
+ rspec-expectations (~> 2.14.0)
70
+ rspec-mocks (~> 2.14.0)
71
+ rspec-core (2.14.7)
72
+ rspec-expectations (2.14.4)
73
+ diff-lcs (>= 1.1.3, < 2.0)
74
+ rspec-instafail (0.2.4)
75
+ rspec-mocks (2.14.4)
76
+ simplecov (0.7.1)
77
+ multi_json (~> 1.0)
78
+ simplecov-html (~> 0.7.1)
79
+ simplecov-html (0.7.1)
65
80
  systemu (2.5.2)
66
81
  trollop (2.0)
67
82
  uuidtools (2.1.4)
@@ -71,4 +86,7 @@ PLATFORMS
71
86
  ruby
72
87
 
73
88
  DEPENDENCIES
89
+ rspec (~> 2.14.1)
90
+ rspec-instafail (~> 0.2.4)
91
+ simplecov
74
92
  stemcell!
@@ -70,12 +70,12 @@ module Stemcell
70
70
 
71
71
  def initialize_launcher
72
72
  @launcher = MetadataLauncher.new(:chef_root => chef_root)
73
- rescue NoTemplateError
73
+ rescue MissingMetadataConfigError
74
74
  puts "Couldn't find `stemcell.json` in the local chef repo.".red
75
75
  puts "You must specify the root of the local checkout of your chef " \
76
76
  "respository by using the --local-chef-root options or " \
77
77
  "setting the LOCAL_CHEF_ROOT environment variable."
78
- rescue TemplateParseError => e
78
+ rescue MetadataConfigParseError => e
79
79
  error "Couldn't parse the `stemcell.json` file: #{e.message}"
80
80
  end
81
81
 
@@ -2,8 +2,9 @@ module Stemcell
2
2
  # This is the class from which all stemcell errors descend.
3
3
  class Error < StandardError; end
4
4
 
5
- class NoTemplateError < Error; end
6
- class TemplateParseError < Error; end
5
+ class MissingMetadataConfigError < Error; end
6
+ class MetadataConfigParseError < Error; end
7
+
7
8
  class RoleExpansionError < Error; end
8
9
  class EmptyRoleError < Error; end
9
10
 
@@ -0,0 +1,55 @@
1
+ require 'chef'
2
+
3
+ module Stemcell
4
+ class MetadataSource
5
+
6
+ class ChefRepository
7
+ include Chef::Mixin::DeepMerge
8
+
9
+ attr_reader :chef_root
10
+
11
+ # Search for instance metadata in the following role attributes, with
12
+ # priority given to the keys at the head.
13
+ METADATA_ATTRIBUTES = [
14
+ :instance_metadata,
15
+ :stemcell
16
+ ]
17
+
18
+ def initialize(chef_root)
19
+ @chef_root = chef_root
20
+ if chef_root.nil?
21
+ raise ArgumentError, "You must specify a chef repository"
22
+ end
23
+
24
+ configure_chef
25
+ end
26
+
27
+ # This method will return nil if the role has no stemcell metdata.
28
+ def metadata_for_role(chef_role, chef_environment)
29
+ default_attrs, override_attrs = expand_role(chef_role, chef_environment)
30
+ merged_attrs = deep_merge!(override_attrs, default_attrs)
31
+ METADATA_ATTRIBUTES.inject(nil) { |r, key| r || merged_attrs[key] }
32
+ end
33
+
34
+ private
35
+
36
+ def configure_chef
37
+ Chef::Config[:cookbook_path] = File.join(chef_root, 'cookbooks')
38
+ Chef::Config[:data_bag_path] = File.join(chef_root, 'data_bags')
39
+ Chef::Config[:role_path] = File.join(chef_root, 'roles')
40
+ end
41
+
42
+ def expand_role(chef_role, chef_environment)
43
+ run_list = Chef::RunList.new
44
+ run_list << "role[#{chef_role}]"
45
+
46
+ expansion = run_list.expand(chef_environment, 'disk')
47
+ raise RoleExpansionError if expansion.errors?
48
+
49
+ [expansion.default_attrs, expansion.override_attrs]
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,77 @@
1
+ require 'json'
2
+
3
+ module Stemcell
4
+ class MetadataSource
5
+
6
+ class Configuration
7
+ attr_reader :config_path
8
+
9
+ attr_reader :all_options
10
+ attr_reader :default_options
11
+ attr_reader :backing_store_options
12
+ attr_reader :availability_zones
13
+
14
+ def initialize(config_path)
15
+ @config_path = config_path
16
+ if config_path.nil?
17
+ raise ArgumentError, "You must specify a configuration file"
18
+ end
19
+
20
+ read_configuration
21
+ validate_configutation
22
+ end
23
+
24
+ def options_for_backing_store(backing_store)
25
+ options = backing_store_options[backing_store]
26
+ raise UnknownBackingStoreError.new(backing_store) if options.nil?
27
+ options
28
+ end
29
+
30
+ def random_az_for_region(region)
31
+ (availability_zones[region] || []).sample
32
+ end
33
+
34
+ private
35
+
36
+ def read_configuration
37
+ begin
38
+ @all_options = JSON.parse(File.read(config_path))
39
+ rescue Errno::ENOENT
40
+ raise Stemcell::MissingMetadataConfigError
41
+ rescue => e
42
+ raise Stemcell::MetadataConfigParseError, e.message
43
+ end
44
+
45
+ @default_options = @all_options['defaults']
46
+ @backing_store_options = @all_options['backing_store']
47
+ @availability_zones = @all_options['availability_zones']
48
+ end
49
+
50
+ def validate_configutation
51
+ errors = []
52
+
53
+ if default_options.nil?
54
+ errors << "missing required section 'defaults'; " \
55
+ "should be a hash containing default launch options"
56
+ end
57
+
58
+ if backing_store_options.nil? || backing_store_options.empty?
59
+ errors << "missing or empty section 'backing_store'"
60
+ errors << "'backing_store' should be a hash from " \
61
+ "store type (like 'ebs') => hash of options for that store"
62
+ end
63
+
64
+ if availability_zones.nil?
65
+ errors << "missing or empty section 'availability_zones'"
66
+ errors << "'availability_zones' should be a hash from " \
67
+ "region name => list of allowed zones in that region"
68
+ end
69
+
70
+ unless errors.empty?
71
+ raise Stemcell::MetadataConfigParseError, errors.join("; ")
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -1,10 +1,18 @@
1
- require 'chef'
2
- require 'json'
1
+ require 'stemcell/metadata_source/chef_repository'
2
+ require 'stemcell/metadata_source/configuration'
3
3
 
4
4
  module Stemcell
5
5
  class MetadataSource
6
+ include Chef::Mixin::DeepMerge
7
+
6
8
  attr_reader :chef_root
7
- attr_reader :default_options
9
+ attr_reader :config_filename
10
+
11
+ attr_reader :config
12
+ attr_reader :chef_repo
13
+
14
+ DEFAULT_CONFIG_FILENAME = 'stemcell.json'
15
+ DEFAULT_BACKING_STORE = 'instance_store'
8
16
 
9
17
  DEFAULT_OPTIONS = {
10
18
  'chef_environment' => 'production',
@@ -14,23 +22,23 @@ module Stemcell
14
22
  'instance_domain_name' => '',
15
23
  }
16
24
 
17
- # Search for instance metadata in the following role attributes, with
18
- # priority given to the keys at the head.
19
- METADATA_ATTRIBUTES = [
20
- :instance_metadata,
21
- :stemcell
22
- ]
23
-
24
- def initialize(chef_root)
25
+ def initialize(chef_root, config_filename=DEFAULT_CONFIG_FILENAME)
25
26
  @chef_root = chef_root
27
+ @config_filename = config_filename
26
28
 
27
- raise ArgumentError, "You must specify a chef root" unless chef_root
29
+ if chef_root.nil?
30
+ raise ArgumentError, "You must specify a chef repository"
31
+ end
32
+ if config_filename.nil?
33
+ raise ArgumentError, "You must specify a configuration file"
34
+ end
28
35
 
29
- template_options = read_template
30
- @default_options = DEFAULT_OPTIONS.merge(template_options['defaults'])
36
+ @config = Configuration.new(File.join(chef_root, config_filename))
37
+ @chef_repo = ChefRepository.new(chef_root)
38
+ end
31
39
 
32
- @all_backing_store_options = template_options['backing_store']
33
- @all_azs_by_region = template_options['availability_zones']
40
+ def default_options
41
+ DEFAULT_OPTIONS.merge(config.default_options)
34
42
  end
35
43
 
36
44
  def expand_role(role, environment, override_options={}, options={})
@@ -38,104 +46,49 @@ module Stemcell
38
46
  raise ArgumentError, "Missing chef environment" unless environment
39
47
  allow_empty_roles = options.fetch(:allow_empty_roles, false)
40
48
 
41
- role_options = expand_role_options(role, environment)
49
+ # Step 1: Expand the role metadata
50
+
51
+ role_options = chef_repo.metadata_for_role(role, environment)
42
52
  role_empty = role_options.nil? || role_options.empty?
43
53
 
44
54
  raise EmptyRoleError if !allow_empty_roles && role_empty
45
55
 
46
- backing_store_options =
47
- expand_backing_store_options(
48
- default_options,
49
- role_options,
50
- override_options
51
- )
52
-
53
- # Merge all the options together in priority order
54
- merged_options = default_options.dup
55
- merged_options.deep_merge!(backing_store_options)
56
- merged_options.deep_merge!(role_options) if role_options
57
- merged_options.deep_merge!(override_options)
58
-
59
- # Add the AZ if not specified
60
- if (region = merged_options['region'])
61
- merged_options['availability_zone'] ||= random_az_in_region(region)
62
- end
56
+ # Step 2: Determine the backing store from available options.
63
57
 
64
- # The chef environment and role used to expand the runlist takes
65
- # priority over all other options.
66
- merged_options['chef_environment'] = environment
67
- merged_options['chef_role'] = role
58
+ # This is determined distinctly from the merge sequence below because
59
+ # the backing store options must be available to the operation.
68
60
 
69
- merged_options
70
- end
61
+ backing_store = override_options['backing_store']
62
+ backing_store ||= role_options.to_hash['backing_store'] if role_options
63
+ backing_store ||= config.default_options['backing_store']
64
+ backing_store ||= DEFAULT_BACKING_STORE
71
65
 
72
- private
66
+ # Step 3: Retrieve the backing store options from the defaults.
73
67
 
74
- def read_template
75
- begin
76
- template_path = File.join(chef_root, 'stemcell.json')
77
- template_options = JSON.parse(IO.read(template_path))
78
- rescue Errno::ENOENT
79
- raise NoTemplateError
80
- rescue => e
81
- raise TemplateParseError, e.message
82
- end
68
+ backing_store_options = config.options_for_backing_store(backing_store)
69
+ backing_store_options['backing_store'] = backing_store
83
70
 
84
- errors = []
85
- unless template_options.include?('defaults')
86
- errors << 'missing required section "defaults"; should be a hash containing default launch options'
87
- end
71
+ # Step 4: Merge the options together in priority order.
88
72
 
89
- if template_options['availability_zones'].nil?
90
- errors << 'missing or empty section "availability zones"'
91
- errors << '"availability_zones" should be a hash from region name => list of allowed zones in that region'
92
- end
73
+ merged_options = DEFAULT_OPTIONS.dup
74
+ merged_options.merge!(config.default_options)
75
+ merged_options.merge!(backing_store_options)
76
+ merged_options.merge!(role_options.to_hash) if role_options
77
+ merged_options.merge!(override_options)
93
78
 
94
- if template_options['backing_store'].nil? or template_options['backing_store'].empty?
95
- errors << 'missing or empty section "backing_store"'
96
- errors << '"backing_store" should be a hash from store type (like "ebs") => hash of options for that store'
97
- end
79
+ # Step 5: If no availability zone was specified, select one at random.
98
80
 
99
- unless errors.empty?
100
- raise TemplateParseError, errors.join("; ")
81
+ if merged_options['availability_zone'].nil? && merged_options['region']
82
+ merged_options['availability_zone'] ||=
83
+ config.random_az_for_region(merged_options['region'])
101
84
  end
102
85
 
103
- return template_options
104
- end
105
-
106
- def expand_role_options(chef_role, chef_environment)
107
- Chef::Config[:role_path] = File.join(chef_root, 'roles')
108
- Chef::Config[:data_bag_path] = File.join(chef_root, 'data_bags')
109
-
110
- run_list = Chef::RunList.new
111
- run_list << "role[#{chef_role}]"
112
-
113
- expansion = run_list.expand(chef_environment, 'disk')
114
- raise RoleExpansionError if expansion.errors?
115
-
116
- default_attrs = expansion.default_attrs
117
- override_attrs = expansion.override_attrs
86
+ # Step 6: Mandate that the environment and role were as specified.
118
87
 
119
- merged_attrs = default_attrs.merge(override_attrs)
120
- METADATA_ATTRIBUTES.inject(nil) { |r, key| r || merged_attrs[key] }
121
- end
122
-
123
- def expand_backing_store_options(default_opts, role_opts, override_opts)
124
- backing_store = override_opts['backing_store']
125
- backing_store ||= role_opts.to_hash['backing_store'] if role_opts
126
- backing_store ||= default_opts['backing_store']
127
- backing_store ||= 'instance_store'
128
-
129
- backing_store_options = @all_backing_store_options[backing_store]
130
- if backing_store_options.nil?
131
- raise Stemcell::UnknownBackingStoreError.new(backing_store)
132
- end
133
- backing_store_options
134
- end
88
+ merged_options['chef_environment'] = environment
89
+ merged_options['chef_role'] = role
135
90
 
136
- def random_az_in_region(region)
137
- possible_azs = @all_azs_by_region[region] || []
138
- possible_azs.sample
91
+ merged_options
139
92
  end
140
93
  end
141
94
  end
@@ -1,3 +1,3 @@
1
1
  module Stemcell
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/stemcell.rb CHANGED
@@ -1,6 +1,4 @@
1
- require 'stemcell/utility'
2
1
  require 'stemcell/errors'
3
-
4
2
  require 'stemcell/command_line'
5
3
  require 'stemcell/option_parser'
6
4
  require 'stemcell/launcher'
@@ -0,0 +1,20 @@
1
+ name 'unit-inherit-base'
2
+ description 'unit-inherit-base'
3
+
4
+ default_attributes({
5
+ 'instance_metadata' => {
6
+ 'instance_type' => 'm1.xlarge',
7
+ 'security_groups' => [
8
+ 'all',
9
+ 'base',
10
+ ],
11
+ 'tags' => {
12
+ 'tag1' => 'tag1_value_base',
13
+ 'tag2' => 'tag2_value',
14
+ },
15
+ },
16
+ })
17
+
18
+ run_list(
19
+ "role[unit-inherit-base]",
20
+ )
@@ -0,0 +1,36 @@
1
+ name 'unit-inherit-both'
2
+ description 'unit-inherit-both'
3
+
4
+ default_attributes({
5
+ 'instance_metadata' => {
6
+ 'instance_type' => 'c1.xlarge',
7
+ 'security_groups' => [
8
+ 'all',
9
+ 'default',
10
+ ],
11
+ 'tags' => {
12
+ 'tag1' => 'tag1_value_default',
13
+ 'tag3' => 'tag3_value_default',
14
+ 'tag4' => 'tag4_value',
15
+ },
16
+ },
17
+ })
18
+
19
+ override_attributes({
20
+ 'instance_metadata' => {
21
+ 'instance_type' => 'm3.xlarge',
22
+ 'security_groups' => [
23
+ 'all',
24
+ 'override',
25
+ ],
26
+ 'tags' => {
27
+ 'tag1' => 'tag1_value_override',
28
+ 'tag3' => 'tag3_value_override',
29
+ 'tag5' => 'tag5_value',
30
+ },
31
+ },
32
+ })
33
+
34
+ run_list(
35
+ "role[unit-inherit-base]",
36
+ )
@@ -0,0 +1,21 @@
1
+ name 'unit-inherit-default'
2
+ description 'unit-inherit-default'
3
+
4
+ default_attributes({
5
+ 'instance_metadata' => {
6
+ 'instance_type' => 'c1.xlarge',
7
+ 'security_groups' => [
8
+ 'all',
9
+ 'default',
10
+ ],
11
+ 'tags' => {
12
+ 'tag1' => 'tag1_value_default',
13
+ 'tag3' => 'tag3_value_default',
14
+ 'tag4' => 'tag4_value',
15
+ },
16
+ },
17
+ })
18
+
19
+ run_list(
20
+ "role[unit-inherit-base]",
21
+ )
@@ -0,0 +1,6 @@
1
+ name 'unit-inherit-none'
2
+ description 'unit-inherit-none'
3
+
4
+ run_list(
5
+ "role[unit-inherit-base]",
6
+ )
@@ -0,0 +1,21 @@
1
+ name 'unit-inherit-override'
2
+ description 'unit-inherit-override'
3
+
4
+ override_attributes({
5
+ 'instance_metadata' => {
6
+ 'instance_type' => 'm3.xlarge',
7
+ 'security_groups' => [
8
+ 'all',
9
+ 'override',
10
+ ],
11
+ 'tags' => {
12
+ 'tag1' => 'tag1_value_override',
13
+ 'tag3' => 'tag3_value_override',
14
+ 'tag5' => 'tag5_value',
15
+ },
16
+ },
17
+ })
18
+
19
+ run_list(
20
+ "role[unit-inherit-base]",
21
+ )
@@ -0,0 +1,29 @@
1
+ name 'unit-simple-both'
2
+ description 'unit-simple-both'
3
+
4
+ default_attributes({
5
+ 'instance_metadata' => {
6
+ 'instance_type' => 'c1.xlarge',
7
+ 'security_groups' => [
8
+ 'all',
9
+ 'default'
10
+ ],
11
+ 'tags' => {
12
+ 'tag1' => 'tag1_value_default',
13
+ 'tag2' => 'tag2_value',
14
+ },
15
+ },
16
+ })
17
+
18
+ override_attributes({
19
+ 'instance_metadata' => {
20
+ 'instance_type' => 'm3.xlarge',
21
+ 'security_groups' => [
22
+ 'override'
23
+ ],
24
+ 'tags' => {
25
+ 'tag1' => 'tag1_value_override',
26
+ 'tag3' => 'tag3_value',
27
+ },
28
+ },
29
+ })
@@ -0,0 +1,16 @@
1
+ name 'unit-simple-default'
2
+ description 'unit-simple-default'
3
+
4
+ default_attributes({
5
+ 'instance_metadata' => {
6
+ 'instance_type' => 'c1.xlarge',
7
+ 'security_groups' => [
8
+ 'all',
9
+ 'default'
10
+ ],
11
+ 'tags' => {
12
+ 'tag1' => 'tag1_value_default',
13
+ 'tag2' => 'tag2_value',
14
+ },
15
+ },
16
+ })
@@ -0,0 +1,2 @@
1
+ name 'unit-simple-none'
2
+ description 'unit-simple-none'
@@ -0,0 +1,16 @@
1
+ name 'unit-simple-override'
2
+ description 'unit-simple-override'
3
+
4
+ override_attributes({
5
+ 'instance_metadata' => {
6
+ 'instance_type' => 'm3.xlarge',
7
+ 'security_groups' => [
8
+ 'all',
9
+ 'override'
10
+ ],
11
+ 'tags' => {
12
+ 'tag1' => 'tag1_value_override',
13
+ 'tag3' => 'tag3_value',
14
+ },
15
+ },
16
+ })
@@ -0,0 +1,16 @@
1
+ {
2
+ "instance_type": "m3.xlarge",
3
+ "security_groups": [
4
+ "all",
5
+ "base",
6
+ "default",
7
+ "override"
8
+ ],
9
+ "tags": {
10
+ "tag1": "tag1_value_override",
11
+ "tag2": "tag2_value",
12
+ "tag3": "tag3_value_override",
13
+ "tag4": "tag4_value",
14
+ "tag5": "tag5_value"
15
+ }
16
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "instance_type": "c1.xlarge",
3
+ "security_groups": [
4
+ "all",
5
+ "base",
6
+ "default"
7
+ ],
8
+ "tags": {
9
+ "tag1": "tag1_value_default",
10
+ "tag2": "tag2_value",
11
+ "tag3": "tag3_value_default",
12
+ "tag4": "tag4_value"
13
+ }
14
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "instance_type": "m1.xlarge",
3
+ "security_groups": [
4
+ "all",
5
+ "base"
6
+ ],
7
+ "tags": {
8
+ "tag1": "tag1_value_base",
9
+ "tag2": "tag2_value"
10
+ }
11
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "instance_type": "m3.xlarge",
3
+ "security_groups": [
4
+ "all",
5
+ "base",
6
+ "override"
7
+ ],
8
+ "tags": {
9
+ "tag1": "tag1_value_override",
10
+ "tag2": "tag2_value",
11
+ "tag3": "tag3_value_override",
12
+ "tag5": "tag5_value"
13
+ }
14
+ }