aws-codedeploy-agent 0.0.2 → 0.0.3

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 (91) hide show
  1. data/aws-codedeploy-agent.gemspec +5 -5
  2. data/certs/host-agent-deployment-signer-ca-chain.pem +30 -0
  3. data/conf/codedeployagent.yml +0 -1
  4. data/lib/instance_agent.rb +1 -13
  5. data/lib/instance_agent/agent/base.rb +38 -12
  6. data/lib/instance_agent/agent/plugin.rb +21 -0
  7. data/lib/instance_agent/config.rb +2 -1
  8. data/lib/instance_agent/platform/linux_util.rb +4 -0
  9. data/lib/instance_agent/plugins/codedeploy/application_specification/ace_info.rb +133 -0
  10. data/lib/instance_agent/plugins/codedeploy/application_specification/acl_info.rb +163 -0
  11. data/lib/instance_agent/plugins/codedeploy/application_specification/application_specification.rb +143 -0
  12. data/lib/instance_agent/plugins/codedeploy/application_specification/context_info.rb +23 -0
  13. data/lib/instance_agent/plugins/codedeploy/application_specification/file_info.rb +23 -0
  14. data/lib/instance_agent/plugins/codedeploy/application_specification/linux_permission_info.rb +121 -0
  15. data/lib/instance_agent/plugins/codedeploy/application_specification/mode_info.rb +66 -0
  16. data/lib/instance_agent/plugins/codedeploy/application_specification/range_info.rb +134 -0
  17. data/lib/instance_agent/plugins/codedeploy/application_specification/script_info.rb +27 -0
  18. data/lib/instance_agent/plugins/codedeploy/codedeploy_control.rb +100 -0
  19. data/lib/instance_agent/plugins/codedeploy/command_executor.rb +359 -0
  20. data/lib/instance_agent/plugins/codedeploy/command_poller.rb +178 -0
  21. data/lib/instance_agent/plugins/codedeploy/deployment_specification.rb +161 -0
  22. data/lib/instance_agent/plugins/codedeploy/hook_executor.rb +226 -0
  23. data/lib/instance_agent/plugins/codedeploy/install_instruction.rb +389 -0
  24. data/lib/instance_agent/plugins/codedeploy/installer.rb +147 -0
  25. data/lib/instance_agent/plugins/codedeploy/onpremise_config.rb +42 -0
  26. data/lib/instance_agent/plugins/codedeploy/register_plugin.rb +17 -0
  27. data/lib/instance_agent/runner/child.rb +20 -5
  28. data/lib/instance_agent/runner/master.rb +2 -15
  29. data/lib/instance_metadata.rb +2 -2
  30. data/test/certificate_helper.rb +1 -1
  31. data/test/helpers/instance_agent_helper.rb +1 -0
  32. data/test/instance_agent/agent/base_test.rb +16 -3
  33. data/test/instance_agent/config_test.rb +2 -1
  34. data/test/instance_agent/plugins/codedeploy/application_specification_test.rb +1713 -0
  35. data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/codedeploy_control_test.rb +1 -1
  36. data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/command_executor_test.rb +32 -9
  37. data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/command_poller_test.rb +13 -14
  38. data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/deployment_specification_test.rb +98 -25
  39. data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/hook_executor_test.rb +83 -15
  40. data/test/instance_agent/plugins/codedeploy/install_instruction_test.rb +568 -0
  41. data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/installer_test.rb +12 -9
  42. data/test/instance_agent/plugins/codedeploy/onpremise_config_test.rb +72 -0
  43. data/test/instance_agent/runner/child_test.rb +1 -1
  44. data/vendor/gems/.codedeploy-commands-1.0.0.created.rid +1 -1
  45. data/vendor/gems/codedeploy-commands/lib/aws/plugins/deploy_control_endpoint.rb +4 -0
  46. data/vendor/gems/jmespath-1.0.1/lib/jmespath.rb +41 -0
  47. data/vendor/gems/jmespath-1.0.1/lib/jmespath/caching_parser.rb +30 -0
  48. data/vendor/gems/jmespath-1.0.1/lib/jmespath/errors.rb +17 -0
  49. data/vendor/gems/jmespath-1.0.1/lib/jmespath/expr_node.rb +15 -0
  50. data/vendor/gems/jmespath-1.0.1/lib/jmespath/lexer.rb +116 -0
  51. data/vendor/gems/jmespath-1.0.1/lib/jmespath/parser.rb +347 -0
  52. data/vendor/gems/jmespath-1.0.1/lib/jmespath/runtime.rb +71 -0
  53. data/vendor/gems/jmespath-1.0.1/lib/jmespath/token.rb +41 -0
  54. data/vendor/gems/jmespath-1.0.1/lib/jmespath/token_stream.rb +60 -0
  55. data/vendor/gems/jmespath-1.0.1/lib/jmespath/tree_interpreter.rb +523 -0
  56. data/vendor/gems/jmespath-1.0.1/lib/jmespath/version.rb +3 -0
  57. data/vendor/gems/process_manager/lib/process_manager/master.rb +16 -5
  58. data/vendor/specifications/{aws-sdk-core-2.0.5.gemspec → aws-sdk-core-2.0.42.gemspec} +9 -11
  59. data/vendor/specifications/builder-3.2.2.gemspec +1 -1
  60. data/vendor/specifications/codedeploy-commands-1.0.0.gemspec +7 -6
  61. data/vendor/specifications/gli-2.5.6.gemspec +1 -1
  62. data/vendor/specifications/jmespath-1.0.1.gemspec +29 -0
  63. data/vendor/specifications/little-plugger-1.1.3.gemspec +1 -1
  64. data/vendor/specifications/logging-1.8.1.gemspec +1 -1
  65. data/vendor/specifications/multi_json-1.7.7.gemspec +1 -1
  66. data/vendor/specifications/multi_json-1.8.4.gemspec +1 -1
  67. data/vendor/specifications/multi_xml-0.5.5.gemspec +1 -1
  68. data/vendor/specifications/process_manager-0.0.13.gemspec +1 -1
  69. data/vendor/specifications/simple_pid-0.2.1.gemspec +1 -1
  70. metadata +76 -63
  71. data/lib/instance_agent/codedeploy_plugin/application_specification/ace_info.rb +0 -133
  72. data/lib/instance_agent/codedeploy_plugin/application_specification/acl_info.rb +0 -163
  73. data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb +0 -142
  74. data/lib/instance_agent/codedeploy_plugin/application_specification/context_info.rb +0 -23
  75. data/lib/instance_agent/codedeploy_plugin/application_specification/file_info.rb +0 -23
  76. data/lib/instance_agent/codedeploy_plugin/application_specification/linux_permission_info.rb +0 -121
  77. data/lib/instance_agent/codedeploy_plugin/application_specification/mode_info.rb +0 -66
  78. data/lib/instance_agent/codedeploy_plugin/application_specification/range_info.rb +0 -134
  79. data/lib/instance_agent/codedeploy_plugin/application_specification/script_info.rb +0 -27
  80. data/lib/instance_agent/codedeploy_plugin/codedeploy_control.rb +0 -72
  81. data/lib/instance_agent/codedeploy_plugin/command_executor.rb +0 -357
  82. data/lib/instance_agent/codedeploy_plugin/command_poller.rb +0 -170
  83. data/lib/instance_agent/codedeploy_plugin/deployment_specification.rb +0 -150
  84. data/lib/instance_agent/codedeploy_plugin/hook_executor.rb +0 -206
  85. data/lib/instance_agent/codedeploy_plugin/install_instruction.rb +0 -374
  86. data/lib/instance_agent/codedeploy_plugin/installer.rb +0 -143
  87. data/lib/instance_agent/codedeploy_plugin/request_helper.rb +0 -28
  88. data/test/instance_agent/codedeploy_plugin/application_specification_test.rb +0 -1710
  89. data/test/instance_agent/codedeploy_plugin/install_instruction_test.rb +0 -566
  90. data/test/instance_agent/codedeploy_plugin/request_helper_test.rb +0 -37
  91. data/vendor/specifications/jamespath-0.5.1.gemspec +0 -35
@@ -0,0 +1,42 @@
1
+ module InstanceAgent
2
+ module Plugins
3
+ module CodeDeployPlugin
4
+ class OnPremisesConfig
5
+ def self.configure
6
+ file_path = InstanceAgent::Config.config[:on_premises_config_file]
7
+ file_config = nil
8
+ if File.exists?(file_path) && File.readable?(file_path)
9
+ begin
10
+ file_config = YAML.load(File.read(file_path)).symbolize_keys
11
+ rescue
12
+ log(:error, "Invalid on premises config file")
13
+ raise "Invalid on premises config file"
14
+ end
15
+ else
16
+ log(:info, "On Premises config file does not exist or not readable")
17
+ end
18
+ if file_config
19
+ if file_config[:region]
20
+ ENV['AWS_REGION'] = file_config[:region]
21
+ end
22
+ if file_config[:aws_access_key_id]
23
+ ENV['AWS_ACCESS_KEY'] = file_config[:aws_access_key_id]
24
+ end
25
+ if file_config[:aws_secret_access_key]
26
+ ENV['AWS_SECRET_KEY'] = file_config[:aws_secret_access_key]
27
+ end
28
+ if file_config[:iam_user_arn]
29
+ ENV['AWS_HOST_IDENTIFIER'] = file_config[:iam_user_arn]
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.log(severity, message)
35
+ raise ArgumentError, "Unknown severity #{severity.inspect}" unless InstanceAgent::Log::SEVERITIES.include?(severity.to_s)
36
+ InstanceAgent::Log.send(severity.to_sym, "#{message}")
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'command_poller'
2
+ require_relative 'command_executor'
3
+ require_relative 'deployment_specification'
4
+ require_relative 'application_specification/application_specification'
5
+ require_relative 'application_specification/file_info'
6
+ require_relative 'application_specification/script_info'
7
+ require_relative 'application_specification/linux_permission_info'
8
+ require_relative 'application_specification/mode_info'
9
+ require_relative 'application_specification/acl_info'
10
+ require_relative 'application_specification/ace_info'
11
+ require_relative 'application_specification/context_info'
12
+ require_relative 'application_specification/range_info'
13
+ require_relative 'installer'
14
+ require_relative 'install_instruction'
15
+ require_relative 'codedeploy_control'
16
+ require_relative 'hook_executor'
17
+ require_relative 'onpremise_config'
@@ -4,16 +4,31 @@ require 'process_manager/child'
4
4
  module InstanceAgent
5
5
  module Runner
6
6
  class Child < ProcessManager::Daemon::Child
7
- AGENTS = {
8
- 0 => InstanceAgent::CodeDeployPlugin::CommandPoller
9
- }
10
7
 
11
8
  attr_accessor :runner
12
9
 
10
+ def load_plugins(plugins)
11
+ ProcessManager::Log.debug("Registering Plugins: #{plugins.inspect}.")
12
+ plugins.each do |plugin|
13
+ plugin_dir = File.expand_path("../plugins/#{plugin}/register_plugin", File.dirname(__FILE__))
14
+ ProcessManager::Log.debug("Loading plugin #{plugin} from #{plugin_dir}")
15
+ begin
16
+ require plugin_dir
17
+ rescue LoadError => e
18
+ ProcessManager::Log.error("Plugin #{plugin} could not be loaded: #{e.message}.")
19
+ raise
20
+ end
21
+ end
22
+ registered_plugins = InstanceAgent::Agent::Base.plugins
23
+ ProcessManager::Log.debug("Registered Plugins: #{registered_plugins.inspect}.")
24
+ Hash[registered_plugins.map.with_index { |value, index| [index, value] }]
25
+ end
26
+
13
27
  def prepare_run
28
+ @plugins ||= load_plugins(ProcessManager::Config.config[:plugins] || ["codedeploy"])
14
29
  validate_index
15
30
  with_error_handling do
16
- @runner = AGENTS[index].runner
31
+ @runner = @plugins[index].runner
17
32
  ProcessManager.set_program_name(description)
18
33
  end
19
34
  end
@@ -33,7 +48,7 @@ module InstanceAgent
33
48
  end
34
49
 
35
50
  def validate_index
36
- raise ArgumentError, "Invalid index #{index.inspect}: only 0-2 possible" unless AGENTS.keys.include?(index)
51
+ raise ArgumentError, "Invalid index #{index.inspect}" unless @plugins.keys.include?(index)
37
52
  end
38
53
 
39
54
  def with_error_handling
@@ -1,7 +1,5 @@
1
1
  # encoding: UTF-8
2
2
  require 'process_manager/master'
3
- require 'instance_agent/codedeploy_plugin/request_helper'
4
- require 'instance_agent/codedeploy_plugin/codedeploy_control'
5
3
  require 'instance_metadata'
6
4
 
7
5
  module InstanceAgent
@@ -22,18 +20,6 @@ module InstanceAgent
22
20
  ProcessManager::Config.config[:program_name]
23
21
  end
24
22
 
25
- def validate_ssl_config
26
- if !InstanceMetadata.instance_id.blank?
27
- region = InstanceMetadata.region
28
- request_helper = InstanceAgent::CodeDeployPlugin::RequestHelper.new(:deploy_control_client => InstanceAgent::CodeDeployPlugin::CodeDeployControl.new(:region => region))
29
-
30
- if (errors = request_helper.verify_clients_configuration)
31
- errors.each{|error| ProcessManager::Log.error("Stopping CodeDeploy agent. " + error)}
32
- end
33
- self.class.abort unless errors.empty?
34
- end
35
- end
36
-
37
23
  def self.log_file
38
24
  File.join(ProcessManager::Config.config[:log_dir], "#{ProcessManager::Config.config[:program_name]}.log")
39
25
  end
@@ -72,7 +58,7 @@ module InstanceAgent
72
58
  end
73
59
 
74
60
  def kill_children(sig)
75
- children.each do |index, child_pid|
61
+ children.each do |index, child_pid|
76
62
  begin
77
63
  Process.kill(sig, child_pid)
78
64
  rescue Errno::ESRCH
@@ -96,6 +82,7 @@ module InstanceAgent
96
82
  end
97
83
  end
98
84
  end
85
+
99
86
  end
100
87
 
101
88
  end
@@ -38,8 +38,8 @@ class InstanceMetadata
38
38
  Net::HTTP.start(IP_ADDRESS, PORT) do |http|
39
39
  response = http.get(path)
40
40
  if response.code.to_i != 200
41
- InstanceAgent::Log.send(:debug, "HTTP error from metadata service, code #{reponse.code}")
42
- raise "HTTP error from metadata service, code #{reponse.code}"
41
+ InstanceAgent::Log.send(:debug, "HTTP error from metadata service, code #{response.code}")
42
+ raise "HTTP error from metadata service, code #{response.code}"
43
43
  end
44
44
  return response.body
45
45
  end
@@ -10,7 +10,7 @@ class CertificateHelper
10
10
  ca_chain_file = generate_ca_chain()
11
11
 
12
12
  ENV['AWS_REGION'] = 'us-east-1'
13
- InstanceAgent::CodeDeployPlugin::DeploymentSpecification.init_cert_store(ca_chain_file)
13
+ InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification.init_cert_store(ca_chain_file)
14
14
  end
15
15
 
16
16
  def generate_root()
@@ -1,5 +1,6 @@
1
1
  # require the code
2
2
  require 'instance_agent'
3
+ require 'instance_agent/plugins/codedeploy/register_plugin'
3
4
 
4
5
  class InstanceAgentTestCase < Test::Unit::TestCase
5
6
  include ActiveSupport::Testing::Assertions
@@ -24,26 +24,39 @@ class InstanceAgentBaseTest < InstanceAgentTestCase
24
24
  end
25
25
 
26
26
  context 'rescues exceptions when running perform' do
27
+ setup do
28
+ @base.stubs(:log).with { |v1, v2| v1.eql?(:debug) }
29
+ end
30
+
27
31
  should 'rescue Aws::Errors::MissingCredentialsError' do
28
32
  @base.stubs(:perform).raises Aws::Errors::MissingCredentialsError
29
- @base.expects(:sleep).with 0
33
+ @base.expects(:sleep).with(9)
30
34
  @base.expects(:log).with(:error, "Missing credentials - please check if this instance was started with an IAM instance profile")
31
35
  assert_nothing_raised(Aws::Errors::MissingCredentialsError) { @base.run }
32
36
  end
33
37
 
34
38
  should 'rescue Aws::Errors::ServiceError' do
35
39
  @base.stubs(:perform).raises Aws::Errors::ServiceError.new(nil, "http error")
36
- @base.expects(:sleep).with(0)
40
+ @base.expects(:sleep).with(9)
37
41
  @base.expects(:log).with { |v1, v2| v1.eql?(:error) && v2 =~ /Cannot reach InstanceService/ }
38
42
  assert_nothing_raised(Aws::Errors::ServiceError) { @base.run }
39
43
  end
40
44
 
41
45
  should 'rescue all other types of exception' do
42
46
  @base.stubs(:perform).raises Exception
43
- @base.expects(:sleep).with(0)
47
+ @base.expects(:sleep).with(9)
44
48
  @base.expects(:log).with { |v1, v2| v1.eql?(:error) && v2 =~ /Error during perform/ }
45
49
  assert_nothing_raised(Exception) { @base.run }
46
50
  end
51
+
52
+ should 'back off on repeated exceptions' do
53
+ @base.stubs(:perform).raises Exception
54
+ @base.expects(:sleep).with(9)
55
+ @base.expects(:sleep).with(12)
56
+ @base.expects(:log).twice.with { |v1, v2| v1.eql?(:error) && v2 =~ /Error during perform/ }
57
+ assert_nothing_raised(Exception) { @base.run }
58
+ assert_nothing_raised(Exception) { @base.run }
59
+ end
47
60
  end
48
61
  end
49
62
  end
@@ -26,7 +26,8 @@ class InstanceAgentConfigTest < InstanceAgentTestCase
26
26
  :instance_service_port => nil,
27
27
  :wait_between_runs => 30,
28
28
  :wait_after_error => 30,
29
- :codedeploy_test_profile => 'prod'
29
+ :codedeploy_test_profile => 'prod',
30
+ :on_premises_config_file => '/etc/codedeploy-agent/conf/codedeploy.onpremises.yml'
30
31
  }, InstanceAgent::Config.config)
31
32
  end
32
33
 
@@ -0,0 +1,1713 @@
1
+ require 'test_helper'
2
+ require 'ostruct'
3
+ require 'yaml'
4
+
5
+ module InstanceAgent
6
+ module Plugins
7
+ module CodeDeployPlugin
8
+ module ApplicationSpecification
9
+ class ApplicationSpecificationTest < InstanceAgentTestCase
10
+ context 'The Application Specification' do
11
+ setup do
12
+ @test_revision_id = 'bar'
13
+ end
14
+
15
+ private
16
+
17
+ def make_app_spec
18
+ ApplicationSpecification.new(YAML.load(@app_spec_string), {:revision_id => @test_revision_id})
19
+ end
20
+
21
+ context "With missing version" do
22
+ setup do
23
+ @app_spec_string = <<-END
24
+ os: linux
25
+ END
26
+ end
27
+
28
+ should "raise an exception" do
29
+ assert_raised_with_message('unsupported version: ',AppSpecValidationException) do
30
+ make_app_spec()
31
+ end
32
+ end
33
+ end
34
+
35
+ context "With invalid version" do
36
+ setup do
37
+ @app_spec_string = <<-END
38
+ version: invalid
39
+ os: linux
40
+ END
41
+ end
42
+
43
+ should "raise an exception" do
44
+ assert_raised_with_message('unsupported version: invalid',AppSpecValidationException) do
45
+ make_app_spec()
46
+ end
47
+ end
48
+ end
49
+
50
+ context "With missing os" do
51
+ setup do
52
+ @app_spec_string = <<-END
53
+ version: 0.0
54
+ END
55
+ end
56
+
57
+ should "raise an exception" do
58
+ assert_raised_with_message('unsupported os: ',AppSpecValidationException) do
59
+ make_app_spec()
60
+ end
61
+ end
62
+ end
63
+
64
+ context "With invalid os" do
65
+ setup do
66
+ @app_spec_string = <<-END
67
+ version: 0.0
68
+ os: unsupported
69
+ END
70
+ end
71
+
72
+ should "raise an exception" do
73
+ assert_raised_with_message('unsupported os: unsupported',AppSpecValidationException) do
74
+ make_app_spec()
75
+ end
76
+ end
77
+ end
78
+
79
+ context "With no hooks or files" do
80
+ setup do
81
+ @app_spec_string = "version: 0.0\nos: linux\n"
82
+ end
83
+ should "Return an empty hooks hash" do
84
+ app_spec = make_app_spec
85
+ assert_equal({}, app_spec.hooks)
86
+ end
87
+ should "Return an empty files array" do
88
+ app_spec = make_app_spec
89
+ assert_equal([], app_spec.files)
90
+ end
91
+ end
92
+
93
+ context "With a single complete hook" do
94
+ setup do
95
+ #A single test script with all parameters
96
+ @app_spec_string = <<-END
97
+ version: 0.0
98
+ os: linux
99
+ hooks:
100
+ test_hook:
101
+ - location: test_location_1
102
+ runas: foo
103
+ timeout: 30
104
+ END
105
+ end
106
+ should "Return a collection containing test script 1" do
107
+ app_spec = make_app_spec
108
+ assert_not_equal nil, app_spec.hooks
109
+ assert_equal ['test_location_1'] , app_spec.hooks["test_hook"].map(&:location)
110
+ assert_equal ['foo'] , app_spec.hooks["test_hook"].map(&:runas)
111
+ assert_equal [30] , app_spec.hooks["test_hook"].map(&:timeout)
112
+ end
113
+ end
114
+
115
+ context "With two complete hooks" do
116
+ setup do
117
+ #A pair of test scripts with all parameters
118
+ @app_spec_string = <<-END
119
+ version: 0.0
120
+ os: linux
121
+ hooks:
122
+ test_hook:
123
+ - location: test_location_1
124
+ runas: foo
125
+ timeout: 30
126
+ - location: test_location_2
127
+ runas: foo2
128
+ timeout: 30
129
+ END
130
+ end
131
+
132
+ should "Return a collection containing test script 1 and test script 2" do
133
+ app_spec = make_app_spec
134
+ assert_not_equal nil, app_spec.hooks
135
+ assert_equal ['test_location_1', 'test_location_2'] , app_spec.hooks["test_hook"].map(&:location)
136
+ end
137
+ end
138
+
139
+ context "With partial hooks (just a runas)" do
140
+ setup do
141
+ #A test script with just a location
142
+ #A test script with location and runas
143
+ @app_spec_string = <<-END
144
+ version: 0.0
145
+ os: linux
146
+ hooks:
147
+ test_hook:
148
+ - location: test_location
149
+ - location: test_location_lr
150
+ runas: foo3
151
+ END
152
+ end
153
+
154
+ should "Return a collection containing the two scripts in order" do
155
+ app_spec = make_app_spec()
156
+ assert_not_equal nil, app_spec.hooks
157
+ assert_equal [nil, 'foo3'] , app_spec.hooks["test_hook"].map(&:runas)
158
+ end
159
+ end
160
+
161
+ context "With partial hooks (just a timeout)" do
162
+ setup do
163
+ #A test script with just a location
164
+ #A test script with location and timeout
165
+ @app_spec_string = <<-END
166
+ version: 0.0
167
+ os: linux
168
+ hooks:
169
+ test_hook:
170
+ - location: test_location
171
+ - location: test_location_lt
172
+ timeout: 30
173
+ END
174
+ end
175
+
176
+ should "Return a collection containing the two scripts in order" do
177
+ app_spec = make_app_spec()
178
+ assert_not_equal nil, app_spec.hooks
179
+ assert_equal [3600, 30] , app_spec.hooks["test_hook"].map(&:timeout)
180
+ end
181
+ end
182
+
183
+ context "With missing location data" do
184
+ setup do
185
+ #A test script without a location
186
+ @app_spec_string = <<-END
187
+ version: 0.0
188
+ os: linux
189
+ hooks:
190
+ test_hook:
191
+ - timeout: 30
192
+ END
193
+ end
194
+
195
+ should "raise an exception" do
196
+ assert_raised_with_message('script provided without a location value',AppSpecValidationException) do
197
+ make_app_spec()
198
+ end
199
+ end
200
+ end
201
+
202
+ context "With non numerical timeout data" do
203
+ setup do
204
+ #A test script with bad timeout data
205
+ @app_spec_string = <<-END
206
+ version: 0.0
207
+ os: linux
208
+ hooks:
209
+ test_hook:
210
+ - location: test_location
211
+ timeout: foo
212
+ END
213
+ end
214
+
215
+ should "raise an exception" do
216
+ assert_raised_with_message('Timeout needs to be an integer greater than 0',AppSpecValidationException) do
217
+ make_app_spec()
218
+ end
219
+ end
220
+ end
221
+
222
+ context "App spec has a file mapping" do
223
+ context "file map contains a single file" do
224
+ setup do
225
+ @app_spec_string = <<-END
226
+ version: 0.0
227
+ os: linux
228
+ files:
229
+ - source: test_source
230
+ destination: test_destination
231
+ END
232
+ end
233
+
234
+ should "return a hash containing the file mapping objects" do
235
+ app_spec = make_app_spec
236
+ assert_not_equal nil, app_spec.files
237
+ assert_equal ['test_source'] , app_spec.files.map(&:source)
238
+ assert_equal ['test_destination'] , app_spec.files.map(&:destination)
239
+ end
240
+ end
241
+
242
+ context "file map contains multiple files" do
243
+ setup do
244
+ @app_spec_string = <<-END
245
+ version: 0.0
246
+ os: linux
247
+ files:
248
+ - source: test_source
249
+ destination: test_destination
250
+ - source: test_source_2
251
+ destination: test_destination_2
252
+ END
253
+ end
254
+
255
+ should "return a hash containing the file mapping objects" do
256
+ app_spec = make_app_spec
257
+ assert_not_equal nil, app_spec.files
258
+ assert_equal ['test_source', 'test_source_2'] , app_spec.files.map(&:source)
259
+ assert_equal ['test_destination','test_destination_2'] , app_spec.files.map(&:destination)
260
+ end
261
+ end
262
+
263
+ context "file map is missing a destination" do
264
+ setup do
265
+ @app_spec_string = <<-END
266
+ version: 0.0
267
+ os: linux
268
+ files:
269
+ - source: test_source
270
+ END
271
+ end
272
+
273
+ should "raise and AppSpecValidationException" do
274
+ assert_raised_with_message('File needs to have a destination',AppSpecValidationException) do
275
+ make_app_spec()
276
+ end
277
+ end
278
+ end
279
+
280
+ context "file map is missing a source" do
281
+ setup do
282
+ @app_spec_string = <<-END
283
+ version: 0.0
284
+ os: linux
285
+ files:
286
+ - destination: test_destination
287
+ END
288
+ end
289
+
290
+ should "raise and AppSpecValidationException" do
291
+ assert_raised_with_message('File needs to have a source',AppSpecValidationException) do
292
+ make_app_spec()
293
+ end
294
+ end
295
+ end
296
+ end
297
+
298
+ context "With permission without object set" do
299
+ setup do
300
+ @app_spec_string = <<-END
301
+ version: 0.0
302
+ os: linux
303
+ permissions:
304
+ - pattern: test
305
+ END
306
+ end
307
+
308
+ should "raise an exception" do
309
+ assert_raised_with_message('permission provided without a object value',AppSpecValidationException) do
310
+ make_app_spec()
311
+ end
312
+ end
313
+ end
314
+
315
+ context "With permission pattern of **" do
316
+ setup do
317
+ @app_spec_string = <<-END
318
+ version: 0.0
319
+ os: linux
320
+ permissions:
321
+ - object: '/'
322
+ pattern: '**'
323
+ END
324
+ end
325
+
326
+ should "match all objects" do
327
+ app_spec = make_app_spec()
328
+ assert_equal '**', app_spec.permissions[0].pattern
329
+ end
330
+ end
331
+
332
+ context "With multiple permissions" do
333
+ setup do
334
+ @app_spec_string = <<-END
335
+ version: 0.0
336
+ os: linux
337
+ permissions:
338
+ - object: '/'
339
+ - object: test
340
+ - object: more
341
+ END
342
+ end
343
+
344
+ should "match all objects" do
345
+ app_spec = make_app_spec()
346
+ assert_equal 3, app_spec.permissions.length
347
+ assert_equal '/', app_spec.permissions[0].object
348
+ assert_equal "test", app_spec.permissions[1].object
349
+ assert_equal "more", app_spec.permissions[2].object
350
+ end
351
+ end
352
+
353
+ context "With permissions with pattern" do
354
+ setup do
355
+ @app_spec_string = <<-END
356
+ version: 0.0
357
+ os: linux
358
+ permissions:
359
+ - object: '/'
360
+ pattern: 'glob'
361
+ END
362
+ end
363
+
364
+ should "raise when validated as file permission" do
365
+ app_spec = make_app_spec()
366
+ assert_raised_with_message('Attempt to use pattern glob when assigning permissions to file /',AppSpecValidationException) do
367
+ app_spec.permissions[0].validate_file_permission
368
+ end
369
+ end
370
+ end
371
+
372
+ context "With permissions with except" do
373
+ setup do
374
+ @app_spec_string = <<-END
375
+ version: 0.0
376
+ os: linux
377
+ permissions:
378
+ - object: '/'
379
+ except:
380
+ - 'glob'
381
+ END
382
+ end
383
+
384
+ should "raise when validated as file permission" do
385
+ app_spec = make_app_spec()
386
+ assert_raised_with_message('Attempt to use except ["glob"] when assigning permissions to file /',AppSpecValidationException) do
387
+ app_spec.permissions[0].validate_file_permission
388
+ end
389
+ end
390
+ end
391
+
392
+ context "With permissions" do
393
+ setup do
394
+ @app_spec_string = <<-END
395
+ version: 0.0
396
+ os: linux
397
+ permissions:
398
+ - object: '/'
399
+ END
400
+ end
401
+
402
+ should "not raise when validated as file permission" do
403
+ app_spec = make_app_spec()
404
+ assert_nothing_raised do
405
+ app_spec.permissions[0].validate_file_permission
406
+ end
407
+ end
408
+ end
409
+
410
+ context "With permissions with pattern without file type" do
411
+ setup do
412
+ @app_spec_string = <<-END
413
+ version: 0.0
414
+ os: linux
415
+ permissions:
416
+ - object: '/'
417
+ pattern: 'glob'
418
+ type:
419
+ - "directory"
420
+ END
421
+ end
422
+
423
+ should "not raise when validated as file permission" do
424
+ app_spec = make_app_spec()
425
+ assert_nothing_raised do
426
+ app_spec.permissions[0].validate_file_permission
427
+ end
428
+ end
429
+ end
430
+
431
+ context "With permissions with acl without default ace" do
432
+ setup do
433
+ @app_spec_string = <<-END
434
+ version: 0.0
435
+ os: linux
436
+ permissions:
437
+ - object: '/'
438
+ acls:
439
+ - 'user:name:rwx'
440
+ END
441
+ end
442
+
443
+ should "be able to validate as a file acl" do
444
+ app_spec = make_app_spec()
445
+ assert_nothing_raised do
446
+ app_spec.permissions[0].validate_file_acl("test")
447
+ end
448
+ end
449
+ end
450
+
451
+ context "With permissions with acl with default ace" do
452
+ setup do
453
+ @app_spec_string = <<-END
454
+ version: 0.0
455
+ os: linux
456
+ permissions:
457
+ - object: '/'
458
+ acls:
459
+ - 'd:user:name:rwx'
460
+ END
461
+ end
462
+
463
+ should "be able to validate as a file acl" do
464
+ app_spec = make_app_spec()
465
+ assert_raised_with_message('Attempt to set default acl default:user:name:rwx on file test',RuntimeError) do
466
+ app_spec.permissions[0].validate_file_acl("test")
467
+ end
468
+ end
469
+ end
470
+
471
+ context "With valid permission object" do
472
+ setup do
473
+ @app_spec_string = <<-END
474
+ version: 0.0
475
+ os: linux
476
+ permissions:
477
+ - object: 'test'
478
+ pattern: 'prefix*'
479
+ except: ['*ReadMe', '*.tmp']
480
+ type: ['file']
481
+ owner: 'bob'
482
+ group: 'dev'
483
+ mode: 6763
484
+ acls:
485
+ - 'u:henry:7'
486
+ - 'd:g:manager:rw'
487
+ context:
488
+ name: 'user_u'
489
+ type: 'unconfined_t'
490
+ range: 's3-s5:c0.c7,c13'
491
+ END
492
+ end
493
+
494
+ should "match pattern when appropriate" do
495
+ app_spec = make_app_spec()
496
+ permission = app_spec.permissions[0]
497
+
498
+ assert permission.matches_pattern?(File.expand_path("test/prefix")), "Should match test/prefix for pattern"
499
+ assert permission.matches_pattern?(File.expand_path("test/prefix_matches")), "Should match test/prefix_matches for pattern"
500
+ assert !permission.matches_pattern?(File.expand_path("test/prefix/does_not_match")), "Should not match test/prefix/does_not_match for pattern"
501
+ assert !permission.matches_pattern?(File.expand_path("testprefix/")), "Should not match testprefix/ for pattern"
502
+ assert !permission.matches_pattern?(File.expand_path("tst/prefix")), "Should not match tst/prefix for pattern"
503
+ assert !permission.matches_pattern?(File.expand_path("test/not_prefix")), "Should not match test/not_prefix for pattern"
504
+ end
505
+
506
+ should "match except when appropriate" do
507
+ app_spec = make_app_spec()
508
+ permission = app_spec.permissions[0]
509
+
510
+ assert permission.matches_except?(File.expand_path("test/this.tmp")), "Should match test/this.tmp for except"
511
+ assert permission.matches_except?(File.expand_path("test/this_ReadMe")), "Should match test/this_ReadMe for except"
512
+ assert !permission.matches_except?(File.expand_path("test/prefix/does_not_match.tmp")), "Should not match test/prefix/does_not_match.tmp for except"
513
+ assert !permission.matches_except?(File.expand_path("testprefix/")), "Should not match testprefix/ for except"
514
+ assert !permission.matches_except?(File.expand_path("tst/prefix")), "Should not match tst/prefix for except"
515
+ assert !permission.matches_except?(File.expand_path("test/not_match")), "Should not match test/not_match for except"
516
+ end
517
+
518
+ should "set fields correctly" do
519
+ app_spec = make_app_spec()
520
+ permission = app_spec.permissions[0]
521
+ assert_equal 'test', permission.object
522
+ assert_equal 'prefix*', permission.pattern
523
+ assert_equal ['*ReadMe', '*.tmp'], permission.except
524
+ assert_equal ['file'], permission.type
525
+ assert_equal 'bob', permission.owner
526
+ assert_equal 'dev', permission.group
527
+
528
+ mode = permission.mode
529
+ assert_equal '6763', mode.mode
530
+ assert_equal '3', mode.world
531
+ assert_equal false, mode.world_readable
532
+ assert_equal true, mode.world_writable
533
+ assert_equal true, mode.world_executable
534
+ assert_equal '6', mode.group
535
+ assert_equal true, mode.group_readable
536
+ assert_equal true, mode.group_writable
537
+ assert_equal false, mode.group_executable
538
+ assert_equal '7', mode.owner
539
+ assert_equal true, mode.owner_readable
540
+ assert_equal true, mode.owner_writable
541
+ assert_equal true, mode.owner_executable
542
+ assert_equal true, mode.setuid
543
+ assert_equal true, mode.setgid
544
+ assert_equal false, mode.sticky
545
+
546
+ acl = permission.acls
547
+ assert_equal 2, acl.aces.length
548
+ ace = acl.aces[0]
549
+ assert_equal false, ace.default
550
+ assert_equal 'user', ace.type
551
+ assert_equal 'henry', ace.name
552
+ assert_equal true, ace.read
553
+ assert_equal true, ace.write
554
+ assert_equal true, ace.execute
555
+
556
+ ace = acl.aces[1]
557
+ assert_equal true, ace.default
558
+ assert_equal 'group', ace.type
559
+ assert_equal 'manager', ace.name
560
+ assert_equal true, ace.read
561
+ assert_equal true, ace.write
562
+ assert_equal false, ace.execute
563
+
564
+ context = permission.context
565
+ assert_equal 'user_u', context.user
566
+ assert_equal nil, context.role
567
+ assert_equal 'unconfined_t', context.type
568
+
569
+ range = context.range
570
+ assert_equal 3, range.low_sensitivity
571
+ assert_equal 5, range.high_sensitivity
572
+
573
+ categories = range.categories
574
+ assert_equal 9, categories.length
575
+ [(0..7).to_a,13].flatten!.each do |category|
576
+ assert_equal true, categories.include?(category), "Unable to find expected category #{category}"
577
+ end
578
+ end
579
+ end
580
+
581
+ context "With permission with acl with ace with too few parts" do
582
+ setup do
583
+ @app_spec_string = <<-END
584
+ version: 0.0
585
+ os: linux
586
+ permissions:
587
+ - object: 'test/'
588
+ acls:
589
+ - '7'
590
+ END
591
+ end
592
+
593
+ should "raise an exception" do
594
+ assert_raised_with_message('invalid acl entry 7',AppSpecValidationException) do
595
+ make_app_spec()
596
+ end
597
+ end
598
+ end
599
+
600
+ context "With permission with acl with ace with too many parts" do
601
+ setup do
602
+ @app_spec_string = <<-END
603
+ version: 0.0
604
+ os: linux
605
+ permissions:
606
+ - object: 'test/'
607
+ acls:
608
+ - 'd:u:bob:7:rwx'
609
+ END
610
+ end
611
+
612
+ should "raise an exception" do
613
+ assert_raised_with_message('invalid acl entry d:u:bob:7:rwx',AppSpecValidationException) do
614
+ make_app_spec()
615
+ end
616
+ end
617
+ end
618
+
619
+ context "With permission with acl with ace with invalid first part" do
620
+ setup do
621
+ @app_spec_string = <<-END
622
+ version: 0.0
623
+ os: linux
624
+ permissions:
625
+ - object: 'test/'
626
+ acls:
627
+ - 'invalid:u:bob:7:rwx'
628
+ END
629
+ end
630
+
631
+ should "raise an exception" do
632
+ assert_raised_with_message('invalid acl entry invalid:u:bob:7:rwx',AppSpecValidationException) do
633
+ make_app_spec()
634
+ end
635
+ end
636
+ end
637
+
638
+ context "With permission with acl with ace with invalid second part" do
639
+ setup do
640
+ @app_spec_string = <<-END
641
+ version: 0.0
642
+ os: linux
643
+ permissions:
644
+ - object: 'test/'
645
+ acls:
646
+ - 'd:invalid:bob:7:rwx'
647
+ END
648
+ end
649
+
650
+ should "raise an exception" do
651
+ assert_raised_with_message('invalid acl entry d:invalid:bob:7:rwx',AppSpecValidationException) do
652
+ make_app_spec()
653
+ end
654
+ end
655
+ end
656
+
657
+ context "With permission with acl with ace with default as first and second part" do
658
+ setup do
659
+ @app_spec_string = <<-END
660
+ version: 0.0
661
+ os: linux
662
+ permissions:
663
+ - object: 'test/'
664
+ acls:
665
+ - 'd:d:bob:7:rwx'
666
+ END
667
+ end
668
+
669
+ should "raise an exception" do
670
+ assert_raised_with_message('invalid acl entry d:d:bob:7:rwx',AppSpecValidationException) do
671
+ make_app_spec()
672
+ end
673
+ end
674
+ end
675
+
676
+ context "With permission with acl with ace with mask with name" do
677
+ setup do
678
+ @app_spec_string = <<-END
679
+ version: 0.0
680
+ os: linux
681
+ permissions:
682
+ - object: 'test/'
683
+ acls:
684
+ - 'mask:name:rwx'
685
+ END
686
+ end
687
+
688
+ should "raise an exception" do
689
+ assert_raised_with_message('invalid acl entry mask:name:rwx',AppSpecValidationException) do
690
+ make_app_spec()
691
+ end
692
+ end
693
+ end
694
+
695
+ context "With permission with acl with ace with other with name" do
696
+ setup do
697
+ @app_spec_string = <<-END
698
+ version: 0.0
699
+ os: linux
700
+ permissions:
701
+ - object: 'test/'
702
+ acls:
703
+ - 'd:other:name:rwx'
704
+ END
705
+ end
706
+
707
+ should "raise an exception" do
708
+ assert_raised_with_message('invalid acl entry d:other:name:rwx',AppSpecValidationException) do
709
+ make_app_spec()
710
+ end
711
+ end
712
+ end
713
+
714
+ context "With permission with acl with ace with invalid permission character" do
715
+ setup do
716
+ @app_spec_string = <<-END
717
+ version: 0.0
718
+ os: linux
719
+ permissions:
720
+ - object: 'test/'
721
+ acls:
722
+ - 'user:bob:rwxd'
723
+ END
724
+ end
725
+
726
+ should "raise an exception" do
727
+ assert_raised_with_message('unrecognized permission character d in user:bob:rwxd',AppSpecValidationException) do
728
+ make_app_spec()
729
+ end
730
+ end
731
+ end
732
+
733
+ context "With permission with acl with valid ace with 4 parts" do
734
+ setup do
735
+ @app_spec_string = <<-END
736
+ version: 0.0
737
+ os: linux
738
+ permissions:
739
+ - object: 'test/'
740
+ acls:
741
+ - 'd:u:bob:rwx'
742
+ - 'default:g:dev:rw'
743
+ END
744
+ end
745
+
746
+ should "generate correct fields" do
747
+ app_spec = make_app_spec()
748
+
749
+ acl = app_spec.permissions[0].acls
750
+ assert_equal 2, acl.aces.length
751
+
752
+ ace = acl.aces[0]
753
+ assert_equal true, ace.default
754
+ assert_equal 'user', ace.type
755
+ assert_equal 'bob', ace.name
756
+ assert_equal true, ace.read
757
+ assert_equal true, ace.write
758
+ assert_equal true, ace.execute
759
+
760
+ ace = acl.aces[1]
761
+ assert_equal true, ace.default
762
+ assert_equal 'group', ace.type
763
+ assert_equal 'dev', ace.name
764
+ assert_equal true, ace.read
765
+ assert_equal true, ace.write
766
+ assert_equal false, ace.execute
767
+ end
768
+ end
769
+
770
+ context "With permission with acl with valid ace with 3 parts" do
771
+ setup do
772
+ @app_spec_string = <<-END
773
+ version: 0.0
774
+ os: linux
775
+ permissions:
776
+ - object: 'test/'
777
+ acls:
778
+ - 'd:bob:rwx'
779
+ - 'default::rw'
780
+ - 'm::7'
781
+ - 'mask::7'
782
+ - 'g:dev:7'
783
+ - 'group:dev:7'
784
+ - 'u:bob:7'
785
+ - 'user:bob:7'
786
+ - 'u:mask:7'
787
+ - 'u:other:7'
788
+ END
789
+ end
790
+
791
+ should "generate correct fields" do
792
+ app_spec = make_app_spec()
793
+
794
+ acl = app_spec.permissions[0].acls
795
+ assert_equal 10, acl.aces.length
796
+
797
+ ace = acl.aces[0]
798
+ assert_equal true, ace.default
799
+ assert_equal 'user', ace.type
800
+ assert_equal 'bob', ace.name
801
+ assert_equal true, ace.read
802
+ assert_equal true, ace.write
803
+ assert_equal true, ace.execute
804
+
805
+ ace = acl.aces[1]
806
+ assert_equal true, ace.default
807
+ assert_equal 'user', ace.type
808
+ assert_equal '', ace.name
809
+ assert_equal true, ace.read
810
+ assert_equal true, ace.write
811
+ assert_equal false, ace.execute
812
+
813
+ ace = acl.aces[2]
814
+ assert_equal false, ace.default
815
+ assert_equal 'mask', ace.type
816
+ assert_equal '', ace.name
817
+ assert_equal true, ace.read
818
+ assert_equal true, ace.write
819
+ assert_equal true, ace.execute
820
+
821
+ ace = acl.aces[3]
822
+ assert_equal false, ace.default
823
+ assert_equal 'mask', ace.type
824
+ assert_equal '', ace.name
825
+ assert_equal true, ace.read
826
+ assert_equal true, ace.write
827
+ assert_equal true, ace.execute
828
+
829
+ ace = acl.aces[4]
830
+ assert_equal false, ace.default
831
+ assert_equal 'group', ace.type
832
+ assert_equal 'dev', ace.name
833
+ assert_equal true, ace.read
834
+ assert_equal true, ace.write
835
+ assert_equal true, ace.execute
836
+
837
+ ace = acl.aces[5]
838
+ assert_equal false, ace.default
839
+ assert_equal 'group', ace.type
840
+ assert_equal 'dev', ace.name
841
+ assert_equal true, ace.read
842
+ assert_equal true, ace.write
843
+ assert_equal true, ace.execute
844
+
845
+ ace = acl.aces[6]
846
+ assert_equal false, ace.default
847
+ assert_equal 'user', ace.type
848
+ assert_equal 'bob', ace.name
849
+ assert_equal true, ace.read
850
+ assert_equal true, ace.write
851
+ assert_equal true, ace.execute
852
+
853
+ ace = acl.aces[7]
854
+ assert_equal false, ace.default
855
+ assert_equal 'user', ace.type
856
+ assert_equal 'bob', ace.name
857
+ assert_equal true, ace.read
858
+ assert_equal true, ace.write
859
+ assert_equal true, ace.execute
860
+
861
+ ace = acl.aces[8]
862
+ assert_equal false, ace.default
863
+ assert_equal 'user', ace.type
864
+ assert_equal 'mask', ace.name
865
+ assert_equal true, ace.read
866
+ assert_equal true, ace.write
867
+ assert_equal true, ace.execute
868
+
869
+ ace = acl.aces[9]
870
+ assert_equal false, ace.default
871
+ assert_equal 'user', ace.type
872
+ assert_equal 'other', ace.name
873
+ assert_equal true, ace.read
874
+ assert_equal true, ace.write
875
+ assert_equal true, ace.execute
876
+ end
877
+ end
878
+
879
+ context "With permission with acl with valid ace with 2 parts" do
880
+ setup do
881
+ @app_spec_string = <<-END
882
+ version: 0.0
883
+ os: linux
884
+ permissions:
885
+ - object: 'test/'
886
+ acls:
887
+ - 'bob:0'
888
+ - 'm:7'
889
+ - 'mask:'
890
+ END
891
+ end
892
+
893
+ should "generate correct fields" do
894
+ app_spec = make_app_spec()
895
+
896
+ acl = app_spec.permissions[0].acls
897
+ assert_equal 3, acl.aces.length
898
+
899
+ ace = acl.aces[0]
900
+ assert_equal false, ace.default
901
+ assert_equal 'user', ace.type
902
+ assert_equal 'bob', ace.name
903
+ assert_equal false, ace.read
904
+ assert_equal false, ace.write
905
+ assert_equal false, ace.execute
906
+
907
+ ace = acl.aces[1]
908
+ assert_equal false, ace.default
909
+ assert_equal 'mask', ace.type
910
+ assert_equal '', ace.name
911
+ assert_equal true, ace.read
912
+ assert_equal true, ace.write
913
+ assert_equal true, ace.execute
914
+
915
+ ace = acl.aces[2]
916
+ assert_equal false, ace.default
917
+ assert_equal 'mask', ace.type
918
+ assert_equal '', ace.name
919
+ assert_equal false, ace.read
920
+ assert_equal false, ace.write
921
+ assert_equal false, ace.execute
922
+ end
923
+ end
924
+
925
+ context "With permission with context with invalid sensitivity range" do
926
+ setup do
927
+ @app_spec_string = <<-END
928
+ version: 0.0
929
+ os: linux
930
+ permissions:
931
+ - object: 'test/'
932
+ context:
933
+ name: 'name'
934
+ type: 'type'
935
+ range: 's3-s2:c0'
936
+ END
937
+ end
938
+
939
+ should "raise an exception" do
940
+ assert_raised_with_message('invalid sensitivity range in s3-s2:c0',AppSpecValidationException) do
941
+ make_app_spec()
942
+ end
943
+ end
944
+ end
945
+
946
+ context "With permission with context with missing sensitivity range part" do
947
+ setup do
948
+ @app_spec_string = <<-END
949
+ version: 0.0
950
+ os: linux
951
+ permissions:
952
+ - object: 'test/'
953
+ context:
954
+ name: 'name'
955
+ type: 'type'
956
+ range: 's3-:c0'
957
+ END
958
+ end
959
+
960
+ should "raise an exception" do
961
+ assert_raised_with_message('invalid range part s3-',AppSpecValidationException) do
962
+ make_app_spec()
963
+ end
964
+ end
965
+ end
966
+
967
+ context "With single sensitivity" do
968
+ setup do
969
+ @app_spec_string = <<-END
970
+ version: 0.0
971
+ os: linux
972
+ permissions:
973
+ - object: 'test/'
974
+ context:
975
+ type: 'type'
976
+ range: 's5'
977
+ END
978
+ end
979
+
980
+ should "generate correct fields" do
981
+ app_spec = make_app_spec()
982
+
983
+ assert_equal 5, app_spec.permissions[0].context.range.low_sensitivity
984
+ assert_equal 5, app_spec.permissions[0].context.range.high_sensitivity
985
+ assert_equal nil, app_spec.permissions[0].context.range.categories
986
+ end
987
+ end
988
+
989
+ context "With permission with context with missing sensitivity" do
990
+ setup do
991
+ @app_spec_string = <<-END
992
+ version: 0.0
993
+ os: linux
994
+ permissions:
995
+ - object: 'test/'
996
+ context:
997
+ name: 'name'
998
+ type: 'type'
999
+ range: ':c0'
1000
+ END
1001
+ end
1002
+
1003
+ should "raise an exception" do
1004
+ assert_raised_with_message('invalid range part :c0',AppSpecValidationException) do
1005
+ make_app_spec()
1006
+ end
1007
+ end
1008
+ end
1009
+
1010
+ context "With permission with context with missing sensitivity value" do
1011
+ setup do
1012
+ @app_spec_string = <<-END
1013
+ version: 0.0
1014
+ os: linux
1015
+ permissions:
1016
+ - object: 'test/'
1017
+ context:
1018
+ name: 'name'
1019
+ type: 'type'
1020
+ range: 's'
1021
+ END
1022
+ end
1023
+
1024
+ should "raise an exception" do
1025
+ assert_raised_with_message('invalid sensitivity s',AppSpecValidationException) do
1026
+ make_app_spec()
1027
+ end
1028
+ end
1029
+ end
1030
+
1031
+ context "With permission with context with negative sensitivity value" do
1032
+ setup do
1033
+ @app_spec_string = <<-END
1034
+ version: 0.0
1035
+ os: linux
1036
+ permissions:
1037
+ - object: 'test/'
1038
+ context:
1039
+ name: 'name'
1040
+ type: 'type'
1041
+ range: 's0-s-1'
1042
+ END
1043
+ end
1044
+
1045
+ should "raise an exception" do
1046
+ assert_raised_with_message('invalid sensitivity s-1',AppSpecValidationException) do
1047
+ make_app_spec()
1048
+ end
1049
+ end
1050
+ end
1051
+
1052
+ context "With permission with context with invalid sensitivity" do
1053
+ setup do
1054
+ @app_spec_string = <<-END
1055
+ version: 0.0
1056
+ os: linux
1057
+ permissions:
1058
+ - object: 'test/'
1059
+ context:
1060
+ name: 'name'
1061
+ type: 'type'
1062
+ range: 'sd3'
1063
+ END
1064
+ end
1065
+
1066
+ should "raise an exception" do
1067
+ assert_raised_with_message('invalid sensitivity sd3',AppSpecValidationException) do
1068
+ make_app_spec()
1069
+ end
1070
+ end
1071
+ end
1072
+
1073
+ context "With permission with context with invalid sensitivity 2" do
1074
+ setup do
1075
+ @app_spec_string = <<-END
1076
+ version: 0.0
1077
+ os: linux
1078
+ permissions:
1079
+ - object: 'test/'
1080
+ context:
1081
+ name: 'name'
1082
+ type: 'type'
1083
+ range: 'd3'
1084
+ END
1085
+ end
1086
+
1087
+ should "raise an exception" do
1088
+ assert_raised_with_message('invalid sensitivity d3',AppSpecValidationException) do
1089
+ make_app_spec()
1090
+ end
1091
+ end
1092
+ end
1093
+
1094
+ context "With permission with context with invalid category range" do
1095
+ setup do
1096
+ @app_spec_string = <<-END
1097
+ version: 0.0
1098
+ os: linux
1099
+ permissions:
1100
+ - object: 'test/'
1101
+ context:
1102
+ name: 'name'
1103
+ type: 'type'
1104
+ range: 's0:c2.c1'
1105
+ END
1106
+ end
1107
+
1108
+ should "raise an exception" do
1109
+ assert_raised_with_message('invalid category range c2.c1',AppSpecValidationException) do
1110
+ make_app_spec()
1111
+ end
1112
+ end
1113
+ end
1114
+
1115
+ context "With permission with context with missing category range part" do
1116
+ setup do
1117
+ @app_spec_string = <<-END
1118
+ version: 0.0
1119
+ os: linux
1120
+ permissions:
1121
+ - object: 'test/'
1122
+ context:
1123
+ name: 'name'
1124
+ type: 'type'
1125
+ range: 's0:c2.'
1126
+ END
1127
+ end
1128
+
1129
+ should "raise an exception" do
1130
+ assert_raised_with_message('invalid range part c2.',AppSpecValidationException) do
1131
+ make_app_spec()
1132
+ end
1133
+ end
1134
+ end
1135
+
1136
+ context "With valid category" do
1137
+ setup do
1138
+ @app_spec_string = <<-END
1139
+ version: 0.0
1140
+ os: linux
1141
+ permissions:
1142
+ - object: 'test/'
1143
+ context:
1144
+ type: 'type'
1145
+ range: 's0:c0.c1,c15,c7.c9'
1146
+ END
1147
+ end
1148
+
1149
+ should "generate correct fields" do
1150
+ app_spec = make_app_spec()
1151
+
1152
+ categories = app_spec.permissions[0].context.range.categories
1153
+ assert_equal 6, categories.length
1154
+ [(0..1).to_a, (7..9).to_a, 15].flatten!.each do |category|
1155
+ assert_equal true, categories.include?(category), "Unable to find expected category #{category}"
1156
+ end
1157
+ end
1158
+ end
1159
+
1160
+ context "With permission with context with missing category" do
1161
+ setup do
1162
+ @app_spec_string = <<-END
1163
+ version: 0.0
1164
+ os: linux
1165
+ permissions:
1166
+ - object: 'test/'
1167
+ context:
1168
+ name: 'name'
1169
+ type: 'type'
1170
+ range: 's0:'
1171
+ END
1172
+ end
1173
+
1174
+ should "raise an exception" do
1175
+ assert_raised_with_message('invalid range part s0:',AppSpecValidationException) do
1176
+ make_app_spec()
1177
+ end
1178
+ end
1179
+ end
1180
+
1181
+ context "With permission with context with missing category value" do
1182
+ setup do
1183
+ @app_spec_string = <<-END
1184
+ version: 0.0
1185
+ os: linux
1186
+ permissions:
1187
+ - object: 'test/'
1188
+ context:
1189
+ name: 'name'
1190
+ type: 'type'
1191
+ range: 's0:c'
1192
+ END
1193
+ end
1194
+
1195
+ should "raise an exception" do
1196
+ assert_raised_with_message('invalid category c',AppSpecValidationException) do
1197
+ make_app_spec()
1198
+ end
1199
+ end
1200
+ end
1201
+
1202
+ context "With permission with context with negative category value" do
1203
+ setup do
1204
+ @app_spec_string = <<-END
1205
+ version: 0.0
1206
+ os: linux
1207
+ permissions:
1208
+ - object: 'test/'
1209
+ context:
1210
+ name: 'name'
1211
+ type: 'type'
1212
+ range: 's0:c-1'
1213
+ END
1214
+ end
1215
+
1216
+ should "raise an exception" do
1217
+ assert_raised_with_message('invalid category c-1',AppSpecValidationException) do
1218
+ make_app_spec()
1219
+ end
1220
+ end
1221
+ end
1222
+
1223
+ context "With permission with context with category value above 1023" do
1224
+ setup do
1225
+ @app_spec_string = <<-END
1226
+ version: 0.0
1227
+ os: linux
1228
+ permissions:
1229
+ - object: 'test/'
1230
+ context:
1231
+ name: 'name'
1232
+ type: 'type'
1233
+ range: 's0:c1024'
1234
+ END
1235
+ end
1236
+
1237
+ should "raise an exception" do
1238
+ assert_raised_with_message('invalid category c1024',AppSpecValidationException) do
1239
+ make_app_spec()
1240
+ end
1241
+ end
1242
+ end
1243
+
1244
+ context "With permission with context without type" do
1245
+ setup do
1246
+ @app_spec_string = <<-END
1247
+ version: 0.0
1248
+ os: linux
1249
+ permissions:
1250
+ - object: 'test/'
1251
+ context:
1252
+ name: 'name'
1253
+ END
1254
+ end
1255
+
1256
+ should "raise an exception" do
1257
+ assert_raised_with_message("invalid context type required {\"name\"=>\"name\"}",AppSpecValidationException) do
1258
+ make_app_spec()
1259
+ end
1260
+ end
1261
+ end
1262
+
1263
+ context "With permission with context with invalid category" do
1264
+ setup do
1265
+ @app_spec_string = <<-END
1266
+ version: 0.0
1267
+ os: linux
1268
+ permissions:
1269
+ - object: 'test/'
1270
+ context:
1271
+ name: 'name'
1272
+ type: 'type'
1273
+ range: 's0:cd3'
1274
+ END
1275
+ end
1276
+
1277
+ should "raise an exception" do
1278
+ assert_raised_with_message('invalid category cd3',AppSpecValidationException) do
1279
+ make_app_spec()
1280
+ end
1281
+ end
1282
+ end
1283
+
1284
+ context "With permission with context with invalid category 2" do
1285
+ setup do
1286
+ @app_spec_string = <<-END
1287
+ version: 0.0
1288
+ os: linux
1289
+ permissions:
1290
+ - object: 'test/'
1291
+ context:
1292
+ name: 'name'
1293
+ type: 'type'
1294
+ range: 's0:d3'
1295
+ END
1296
+ end
1297
+
1298
+ should "raise an exception" do
1299
+ assert_raised_with_message('invalid category d3',AppSpecValidationException) do
1300
+ make_app_spec()
1301
+ end
1302
+ end
1303
+ end
1304
+
1305
+ context "With permission with context with duplicate categories" do
1306
+ setup do
1307
+ @app_spec_string = <<-END
1308
+ version: 0.0
1309
+ os: linux
1310
+ permissions:
1311
+ - object: 'test/'
1312
+ context:
1313
+ name: 'name'
1314
+ type: 'type'
1315
+ range: 's0:c0.c2,c1'
1316
+ END
1317
+ end
1318
+
1319
+ should "raise an exception" do
1320
+ assert_raised_with_message('duplicate categories',AppSpecValidationException) do
1321
+ make_app_spec()
1322
+ end
1323
+ end
1324
+ end
1325
+
1326
+ context "With permission with mode with 5 digits" do
1327
+ setup do
1328
+ @app_spec_string = <<-END
1329
+ version: 0.0
1330
+ os: linux
1331
+ permissions:
1332
+ - object: 'test/'
1333
+ mode: 12345
1334
+ END
1335
+ end
1336
+
1337
+ should "raise an exception" do
1338
+ assert_raised_with_message('permission mode length incorrect: 12345',AppSpecValidationException) do
1339
+ make_app_spec()
1340
+ end
1341
+ end
1342
+ end
1343
+
1344
+ context "With permission with mode with 2 digits" do
1345
+ setup do
1346
+ @app_spec_string = <<-END
1347
+ version: 0.0
1348
+ os: linux
1349
+ permissions:
1350
+ - object: 'test/'
1351
+ mode: 12
1352
+ END
1353
+ end
1354
+
1355
+ should "fill in needed zeros" do
1356
+ app_spec = make_app_spec()
1357
+
1358
+ mode = app_spec.permissions[0].mode
1359
+ assert_equal '012', mode.mode
1360
+ assert_equal '2', mode.world
1361
+ assert_equal false, mode.world_readable
1362
+ assert_equal true, mode.world_writable
1363
+ assert_equal false, mode.world_executable
1364
+ assert_equal '1', mode.group
1365
+ assert_equal false, mode.group_readable
1366
+ assert_equal false, mode.group_writable
1367
+ assert_equal true, mode.group_executable
1368
+ assert_equal '0', mode.owner
1369
+ assert_equal false, mode.owner_readable
1370
+ assert_equal false, mode.owner_writable
1371
+ assert_equal false, mode.owner_executable
1372
+ assert_equal false, mode.setuid
1373
+ assert_equal false, mode.setgid
1374
+ assert_equal false, mode.sticky
1375
+ end
1376
+ end
1377
+
1378
+ context "With permission with mode with invalid char" do
1379
+ setup do
1380
+ @app_spec_string = <<-END
1381
+ version: 0.0
1382
+ os: linux
1383
+ permissions:
1384
+ - object: 'test/'
1385
+ mode: 12a
1386
+ END
1387
+ end
1388
+
1389
+ should "raise an exception" do
1390
+ assert_raised_with_message('invalid character a in permission mode 12a',AppSpecValidationException) do
1391
+ make_app_spec()
1392
+ end
1393
+ end
1394
+ end
1395
+
1396
+ context "With permission with valid modes" do
1397
+ setup do
1398
+ @app_spec_string = <<-END
1399
+ version: 0.0
1400
+ os: linux
1401
+ permissions:
1402
+ - object: 'test/'
1403
+ mode: 7777
1404
+ - object: 'test1/'
1405
+ mode: 0000
1406
+ - object: 'test2/'
1407
+ mode: 777
1408
+ END
1409
+ end
1410
+
1411
+ should "generate correct fields" do
1412
+ app_spec = make_app_spec()
1413
+
1414
+ mode = app_spec.permissions[0].mode
1415
+ assert_equal '7777', mode.mode
1416
+ assert_equal '7', mode.world
1417
+ assert_equal true, mode.world_readable
1418
+ assert_equal true, mode.world_writable
1419
+ assert_equal true, mode.world_executable
1420
+ assert_equal '7', mode.group
1421
+ assert_equal true, mode.group_readable
1422
+ assert_equal true, mode.group_writable
1423
+ assert_equal true, mode.group_executable
1424
+ assert_equal '7', mode.owner
1425
+ assert_equal true, mode.owner_readable
1426
+ assert_equal true, mode.owner_writable
1427
+ assert_equal true, mode.owner_executable
1428
+ assert_equal true, mode.setuid
1429
+ assert_equal true, mode.setgid
1430
+ assert_equal true, mode.sticky
1431
+
1432
+ mode = app_spec.permissions[1].mode
1433
+ assert_equal '000', mode.mode
1434
+ assert_equal '0', mode.world
1435
+ assert_equal false, mode.world_readable
1436
+ assert_equal false, mode.world_writable
1437
+ assert_equal false, mode.world_executable
1438
+ assert_equal '0', mode.group
1439
+ assert_equal false, mode.group_readable
1440
+ assert_equal false, mode.group_writable
1441
+ assert_equal false, mode.group_executable
1442
+ assert_equal '0', mode.owner
1443
+ assert_equal false, mode.owner_readable
1444
+ assert_equal false, mode.owner_writable
1445
+ assert_equal false, mode.owner_executable
1446
+ assert_equal false, mode.setuid
1447
+ assert_equal false, mode.setgid
1448
+ assert_equal false, mode.sticky
1449
+
1450
+ mode = app_spec.permissions[2].mode
1451
+ assert_equal '777', mode.mode
1452
+ assert_equal '7', mode.world
1453
+ assert_equal true, mode.world_readable
1454
+ assert_equal true, mode.world_writable
1455
+ assert_equal true, mode.world_executable
1456
+ assert_equal '7', mode.group
1457
+ assert_equal true, mode.group_readable
1458
+ assert_equal true, mode.group_writable
1459
+ assert_equal true, mode.group_executable
1460
+ assert_equal '7', mode.owner
1461
+ assert_equal true, mode.owner_readable
1462
+ assert_equal true, mode.owner_writable
1463
+ assert_equal true, mode.owner_executable
1464
+ assert_equal false, mode.setuid
1465
+ assert_equal false, mode.setgid
1466
+ assert_equal false, mode.sticky
1467
+ end
1468
+ end
1469
+
1470
+ context "When acl is present" do
1471
+ setup do
1472
+ @app_spec_string = <<-END
1473
+ version: 0.0
1474
+ os: linux
1475
+ permissions:
1476
+ - object: 'test/'
1477
+ acls: []
1478
+ END
1479
+ app_spec = make_app_spec()
1480
+ @acl = app_spec.permissions[0].acls
1481
+ end
1482
+
1483
+ should "be able to add and clear additional aces" do
1484
+ @acl.add_ace("d:henry:4")
1485
+ @acl.clear_additional
1486
+ end
1487
+
1488
+ should "be able to get an empty acl" do
1489
+ assert_equal [], @acl.get_acl
1490
+ end
1491
+
1492
+ should "be able to get added aces in the acl" do
1493
+ @acl.add_ace("d:henry:4")
1494
+ assert_equal 1, @acl.get_acl.length
1495
+ @acl.clear_additional
1496
+ end
1497
+
1498
+ should "not be able to get a default ace" do
1499
+ assert_equal nil, @acl.get_default_ace
1500
+ end
1501
+
1502
+ should "be able to get an added default ace" do
1503
+ @acl.add_ace("d:henry:4")
1504
+ assert_not_nil @acl.get_default_ace
1505
+ @acl.clear_additional
1506
+ end
1507
+
1508
+ should "not be able to get a default group ace" do
1509
+ assert_equal nil, @acl.get_default_group_ace
1510
+ end
1511
+
1512
+ should "be able to get an added default group ace" do
1513
+ @acl.add_ace("d:g::4")
1514
+ assert_not_nil @acl.get_default_group_ace
1515
+ @acl.clear_additional
1516
+ end
1517
+
1518
+ should "not have a base named ace" do
1519
+ assert !@acl.has_base_named?
1520
+ end
1521
+
1522
+ should "have a base named ace when added" do
1523
+ @acl.add_ace("bob:4")
1524
+ assert @acl.has_base_named?
1525
+ @acl.clear_additional
1526
+ end
1527
+
1528
+ should "not have a base mask ace" do
1529
+ assert !@acl.has_base_mask?
1530
+ end
1531
+
1532
+ should "have a base mask ace when added" do
1533
+ @acl.add_ace("m:4")
1534
+ assert @acl.has_base_mask?
1535
+ @acl.clear_additional
1536
+ end
1537
+
1538
+ should "not have a default ace" do
1539
+ assert !@acl.has_default?
1540
+ end
1541
+
1542
+ should "have a default ace when added" do
1543
+ @acl.add_ace("d:bob:4")
1544
+ assert @acl.has_default?
1545
+ @acl.clear_additional
1546
+ end
1547
+
1548
+ should "not have a default user ace" do
1549
+ assert !@acl.has_default_user?
1550
+ end
1551
+
1552
+ should "have a default user ace when added" do
1553
+ @acl.add_ace("d::4")
1554
+ assert @acl.has_default_user?
1555
+ @acl.clear_additional
1556
+ end
1557
+
1558
+ should "not have a default group ace" do
1559
+ assert !@acl.has_default_group?
1560
+ end
1561
+
1562
+ should "have a default group ace when added" do
1563
+ @acl.add_ace("d:g::4")
1564
+ assert @acl.has_default_group?
1565
+ @acl.clear_additional
1566
+ end
1567
+
1568
+ should "not have a default other ace" do
1569
+ assert !@acl.has_default_other?
1570
+ end
1571
+
1572
+ should "have a default other ace when added" do
1573
+ @acl.add_ace("d:o:4")
1574
+ assert @acl.has_default_other?
1575
+ @acl.clear_additional
1576
+ end
1577
+
1578
+ should "not have a default named ace" do
1579
+ assert !@acl.has_default_named?
1580
+ end
1581
+
1582
+ should "have a default named ace when added" do
1583
+ @acl.add_ace("d:bob:4")
1584
+ assert @acl.has_default_named?
1585
+ @acl.clear_additional
1586
+ end
1587
+
1588
+ should "not have a default mask ace" do
1589
+ assert !@acl.has_default_mask?
1590
+ end
1591
+
1592
+ should "have a default mask ace when added" do
1593
+ @acl.add_ace("d:m:4")
1594
+ assert @acl.has_default_mask?
1595
+ @acl.clear_additional
1596
+ end
1597
+ end
1598
+
1599
+ context "When acl is present with existing aces" do
1600
+ setup do
1601
+ @app_spec_string = <<-END
1602
+ version: 0.0
1603
+ os: linux
1604
+ permissions:
1605
+ - object: 'test/'
1606
+ acls:
1607
+ - 'bob:6'
1608
+ - 'm:6'
1609
+ - 'd:bob:0'
1610
+ - 'd::3'
1611
+ - 'd:g::4'
1612
+ - 'd:o:3'
1613
+ - 'd:m:7'
1614
+ END
1615
+ app_spec = make_app_spec()
1616
+ @acl = app_spec.permissions[0].acls
1617
+ end
1618
+
1619
+ should "be able to get the acl" do
1620
+ assert_equal 7, @acl.get_acl.length
1621
+ end
1622
+
1623
+ should "be able to get default ace" do
1624
+ assert_not_nil @acl.get_default_ace
1625
+ end
1626
+
1627
+ should "be able to get default group ace" do
1628
+ assert_not_nil @acl.get_default_group_ace
1629
+ end
1630
+
1631
+ should "have base named ace" do
1632
+ assert_not_nil @acl.has_base_named?
1633
+ end
1634
+
1635
+ should "have base mask ace" do
1636
+ assert_not_nil @acl.has_base_mask?
1637
+ end
1638
+
1639
+ should "have default ace" do
1640
+ assert_not_nil @acl.has_default?
1641
+ end
1642
+
1643
+ should "have default user ace" do
1644
+ assert_not_nil @acl.has_default_user?
1645
+ end
1646
+
1647
+ should "have default group ace" do
1648
+ assert_not_nil @acl.has_default_group?
1649
+ end
1650
+
1651
+ should "have default other ace" do
1652
+ assert_not_nil @acl.has_default_other?
1653
+ end
1654
+
1655
+ should "have default named ace" do
1656
+ assert_not_nil @acl.has_default_named?
1657
+ end
1658
+
1659
+ should "have default mask ace" do
1660
+ assert_not_nil @acl.has_default_mask?
1661
+ end
1662
+ end
1663
+ end
1664
+
1665
+ context "With a ContextInfo" do
1666
+ should "with a simple range" do
1667
+ info = InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::ContextInfo.new({"type"=>"type","range"=>"s3"})
1668
+ assert_equal "s3", info.range.get_range
1669
+ end
1670
+
1671
+ should "with a complex range" do
1672
+ info = InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::ContextInfo.new({"type"=>"type","range"=>"s3-s7:c5,c8.c10,c17"})
1673
+ assert_equal "s3-s7:c5,c8.c10,c17", info.range.get_range
1674
+ end
1675
+ end
1676
+
1677
+ context "With a ACEInfo" do
1678
+ should "not raise if made internal with base entries" do
1679
+ assert_nothing_raised do
1680
+ InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("u::7", true)
1681
+ InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("g::7", true)
1682
+ InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("o::7", true)
1683
+ end
1684
+ end
1685
+
1686
+ should "raise when not internal and has base user" do
1687
+ assert_raised_with_message("use mode to set the base acl entry u::7",AppSpecValidationException) do
1688
+ InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("u::7")
1689
+ end
1690
+ end
1691
+
1692
+ should "raise when not internal and has base group" do
1693
+ assert_raised_with_message("use mode to set the base acl entry g::7",AppSpecValidationException) do
1694
+ InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("g::7")
1695
+ end
1696
+ end
1697
+
1698
+ should "raise when not internal and has base other" do
1699
+ assert_raised_with_message("use mode to set the base acl entry o:7",AppSpecValidationException) do
1700
+ InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("o:7")
1701
+ end
1702
+ end
1703
+
1704
+ should "be able to get the ace" do
1705
+ assert_equal("default:user:bob:rwx", InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("d:u:bob:7").get_ace)
1706
+ assert_equal("mask::---", InstanceAgent::Plugins::CodeDeployPlugin::ApplicationSpecification::AceInfo.new("m:0").get_ace)
1707
+ end
1708
+ end
1709
+ end
1710
+ end
1711
+ end
1712
+ end
1713
+ end