aws-codedeploy-agent 0.0.1
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.
- data/.gitignore +2 -0
- data/CHANGES.md +3 -0
- data/Gemfile +13 -0
- data/LICENSE +177 -0
- data/NOTICE +2 -0
- data/README.md +16 -0
- data/aws-codedeploy-agent.gemspec +39 -0
- data/bin/codedeploy-agent +78 -0
- data/bin/codedeploy-install +15 -0
- data/bin/codedeploy-uninstall +13 -0
- data/certs/host-agent-deployment-signer-ca-chain.pem +76 -0
- data/conf/codedeployagent.yml +9 -0
- data/init.d/codedeploy-agent +61 -0
- data/lib/core_ext.rb +71 -0
- data/lib/instance_agent.rb +35 -0
- data/lib/instance_agent/agent/base.rb +34 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/ace_info.rb +133 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/acl_info.rb +163 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb +142 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/context_info.rb +23 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/file_info.rb +23 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/linux_permission_info.rb +121 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/mode_info.rb +66 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/range_info.rb +134 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/script_info.rb +27 -0
- data/lib/instance_agent/codedeploy_plugin/codedeploy_control.rb +72 -0
- data/lib/instance_agent/codedeploy_plugin/command_executor.rb +357 -0
- data/lib/instance_agent/codedeploy_plugin/command_poller.rb +146 -0
- data/lib/instance_agent/codedeploy_plugin/deployment_specification.rb +150 -0
- data/lib/instance_agent/codedeploy_plugin/hook_executor.rb +206 -0
- data/lib/instance_agent/codedeploy_plugin/install_instruction.rb +374 -0
- data/lib/instance_agent/codedeploy_plugin/installer.rb +143 -0
- data/lib/instance_agent/codedeploy_plugin/request_helper.rb +28 -0
- data/lib/instance_agent/config.rb +43 -0
- data/lib/instance_agent/log.rb +3 -0
- data/lib/instance_agent/platform.rb +17 -0
- data/lib/instance_agent/platform/linux_util.rb +57 -0
- data/lib/instance_agent/runner/child.rb +57 -0
- data/lib/instance_agent/runner/master.rb +103 -0
- data/lib/instance_metadata.rb +47 -0
- data/test/certificate_helper.rb +120 -0
- data/test/helpers/instance_agent_helper.rb +25 -0
- data/test/instance_agent/agent/base_test.rb +49 -0
- data/test/instance_agent/codedeploy_plugin/application_specification_test.rb +1710 -0
- data/test/instance_agent/codedeploy_plugin/codedeploy_control_test.rb +51 -0
- data/test/instance_agent/codedeploy_plugin/command_executor_test.rb +513 -0
- data/test/instance_agent/codedeploy_plugin/command_poller_test.rb +459 -0
- data/test/instance_agent/codedeploy_plugin/deployment_specification_test.rb +335 -0
- data/test/instance_agent/codedeploy_plugin/hook_executor_test.rb +250 -0
- data/test/instance_agent/codedeploy_plugin/install_instruction_test.rb +566 -0
- data/test/instance_agent/codedeploy_plugin/installer_test.rb +519 -0
- data/test/instance_agent/codedeploy_plugin/request_helper_test.rb +37 -0
- data/test/instance_agent/config_test.rb +64 -0
- data/test/instance_agent/runner/child_test.rb +87 -0
- data/test/instance_metadata_test.rb +97 -0
- data/test/test_helper.rb +16 -0
- data/vendor/gems/.codedeploy-commands-1.0.0.created.rid +1 -0
- data/vendor/gems/codedeploy-commands/apis/CodeDeployCommand.api.json +372 -0
- data/vendor/gems/codedeploy-commands/codedeploy-commands-1.0.0.gemspec +28 -0
- data/vendor/gems/codedeploy-commands/lib/aws/codedeploy_commands.rb +18 -0
- data/vendor/gems/codedeploy-commands/lib/aws/plugins/certificate_authority.rb +12 -0
- data/vendor/gems/codedeploy-commands/lib/aws/plugins/deploy_control_endpoint.rb +22 -0
- data/vendor/gems/process_manager/README.md +1 -0
- data/vendor/gems/process_manager/lib/blank.rb +153 -0
- data/vendor/gems/process_manager/lib/core_ext.rb +73 -0
- data/vendor/gems/process_manager/lib/process_manager.rb +49 -0
- data/vendor/gems/process_manager/lib/process_manager/child.rb +119 -0
- data/vendor/gems/process_manager/lib/process_manager/config.rb +112 -0
- data/vendor/gems/process_manager/lib/process_manager/log.rb +107 -0
- data/vendor/gems/process_manager/lib/process_manager/master.rb +322 -0
- data/vendor/gems/process_manager/process_manager-0.0.13.gemspec +42 -0
- data/vendor/specifications/aws-sdk-core-2.0.5.gemspec +39 -0
- data/vendor/specifications/builder-3.2.2.gemspec +29 -0
- data/vendor/specifications/codedeploy-commands-1.0.0.gemspec +28 -0
- data/vendor/specifications/gli-2.5.6.gemspec +51 -0
- data/vendor/specifications/jamespath-0.5.1.gemspec +35 -0
- data/vendor/specifications/little-plugger-1.1.3.gemspec +32 -0
- data/vendor/specifications/logging-1.8.1.gemspec +44 -0
- data/vendor/specifications/multi_json-1.7.7.gemspec +30 -0
- data/vendor/specifications/multi_json-1.8.4.gemspec +30 -0
- data/vendor/specifications/multi_xml-0.5.5.gemspec +30 -0
- data/vendor/specifications/process_manager-0.0.13.gemspec +42 -0
- data/vendor/specifications/simple_pid-0.2.1.gemspec +28 -0
- metadata +377 -0
data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
module InstanceAgent
|
|
2
|
+
module CodeDeployPlugin
|
|
3
|
+
module ApplicationSpecification
|
|
4
|
+
|
|
5
|
+
class AppSpecValidationException < Exception; end
|
|
6
|
+
class ApplicationSpecification
|
|
7
|
+
|
|
8
|
+
attr_reader :version, :os, :hooks, :files, :permissions
|
|
9
|
+
|
|
10
|
+
def initialize(yaml_hash, opts = {})
|
|
11
|
+
@version = parse_version(yaml_hash['version'])
|
|
12
|
+
@os = parse_os(yaml_hash['os'])
|
|
13
|
+
@hooks = parse_hooks(yaml_hash['hooks'] || {})
|
|
14
|
+
@files = parse_files(yaml_hash['files'] || [])
|
|
15
|
+
@permissions = parse_permissions(yaml_hash['permissions'] || [])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.parse(app_spec_string)
|
|
19
|
+
new(YAML.load(app_spec_string))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
def supported_versions()
|
|
24
|
+
[0.0]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def parse_version(version)
|
|
28
|
+
if !supported_versions.include?(version)
|
|
29
|
+
raise AppSpecValidationException, "unsupported version: #{version}"
|
|
30
|
+
end
|
|
31
|
+
version
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def supported_oses()
|
|
35
|
+
InstanceAgent::Platform.util.supported_oses()
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parse_os(os)
|
|
39
|
+
if !supported_oses.include?(os)
|
|
40
|
+
raise AppSpecValidationException, "unsupported os: #{os}"
|
|
41
|
+
end
|
|
42
|
+
os
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def parse_files(file_map_hash)
|
|
46
|
+
files = []
|
|
47
|
+
#loop through hash and create fileInfo representations
|
|
48
|
+
file_map_hash.each do |mapping|
|
|
49
|
+
files << FileInfo.new(mapping['source'], mapping['destination'])
|
|
50
|
+
end
|
|
51
|
+
files
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def parse_hooks(hooks_hash)
|
|
55
|
+
temp_hooks_hash = Hash.new
|
|
56
|
+
hooks_hash.each_pair do |hook, scripts|
|
|
57
|
+
current_hook_scripts = []
|
|
58
|
+
scripts.each do |script|
|
|
59
|
+
if (script.has_key?('location'))
|
|
60
|
+
current_hook_scripts << InstanceAgent::CodeDeployPlugin::ApplicationSpecification::ScriptInfo.new(script['location'].strip,
|
|
61
|
+
{
|
|
62
|
+
:runas => script.has_key?('runas') ? script['runas'].strip : nil,
|
|
63
|
+
:timeout => script['timeout']
|
|
64
|
+
})
|
|
65
|
+
else
|
|
66
|
+
raise AppSpecValidationException, 'script provided without a location value'
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
temp_hooks_hash[hook] = current_hook_scripts
|
|
70
|
+
end
|
|
71
|
+
temp_hooks_hash
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def parse_permissions(permissions_list)
|
|
75
|
+
permissions = []
|
|
76
|
+
#loop through list and create permissionsInfo representations
|
|
77
|
+
permissions_list.each do |permission|
|
|
78
|
+
if !permission.has_key?('object')
|
|
79
|
+
raise AppSpecValidationException, 'permission provided without a object value'
|
|
80
|
+
end
|
|
81
|
+
if @os.eql?('linux')
|
|
82
|
+
permissions << InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new(permission['object'].strip,
|
|
83
|
+
{
|
|
84
|
+
:pattern => ('**'.eql?(permission['pattern']) || permission['pattern'].nil?) ? '**' : parse_simple_glob(permission['pattern']),
|
|
85
|
+
:except => parse_simple_glob_list(permission['except']),
|
|
86
|
+
:type => parse_type_list(permission['type']),
|
|
87
|
+
:owner => permission['owner'],
|
|
88
|
+
:group => permission['group'],
|
|
89
|
+
:mode => parse_mode(permission['mode']),
|
|
90
|
+
:acls => parse_acl(permission['acls']),
|
|
91
|
+
:context => parse_context(permission['context'])
|
|
92
|
+
})
|
|
93
|
+
else
|
|
94
|
+
raise AppSpecValidationException, 'permissions only supported with linux os currently'
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
permissions
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
#placeholder for parsing globs: we should verify that the glob is only including what we expect. For now just returning it as it is.
|
|
101
|
+
def parse_simple_glob(glob)
|
|
102
|
+
glob
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def parse_simple_glob_list(glob_list)
|
|
106
|
+
temp_glob_list = []
|
|
107
|
+
(glob_list || []).each do |glob|
|
|
108
|
+
temp_glob_list << parse_simple_glob(glob)
|
|
109
|
+
end
|
|
110
|
+
temp_glob_list
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def supported_types
|
|
114
|
+
['file', 'directory']
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def parse_type_list(type_list)
|
|
118
|
+
type_list ||= supported_types
|
|
119
|
+
type_list.each do |type|
|
|
120
|
+
if !supported_types.include?(type)
|
|
121
|
+
raise AppSpecValidationException, "assigning permissions to objects of type #{type} not supported"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
type_list
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def parse_mode(mode)
|
|
128
|
+
mode.nil? ? nil : InstanceAgent::CodeDeployPlugin::ApplicationSpecification::ModeInfo.new(mode)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def parse_acl(acl)
|
|
132
|
+
acl.nil? ? nil : InstanceAgent::CodeDeployPlugin::ApplicationSpecification::AclInfo.new(acl)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def parse_context(context)
|
|
136
|
+
context.nil? ? nil : InstanceAgent::CodeDeployPlugin::ApplicationSpecification::ContextInfo.new(context)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module InstanceAgent
|
|
2
|
+
module CodeDeployPlugin
|
|
3
|
+
module ApplicationSpecification
|
|
4
|
+
|
|
5
|
+
#Helper Class for storing a context
|
|
6
|
+
class ContextInfo
|
|
7
|
+
|
|
8
|
+
attr_reader :user, :role, :type, :range
|
|
9
|
+
|
|
10
|
+
def initialize(context)
|
|
11
|
+
if context['type'].nil?
|
|
12
|
+
raise AppSpecValidationException, "invalid context type required #{context.inspect}"
|
|
13
|
+
end
|
|
14
|
+
@user = context['name']
|
|
15
|
+
@role = nil
|
|
16
|
+
@type = context['type']
|
|
17
|
+
@range = context['range'].nil? ? nil : RangeInfo.new(context['range'])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module InstanceAgent
|
|
2
|
+
module CodeDeployPlugin
|
|
3
|
+
module ApplicationSpecification
|
|
4
|
+
|
|
5
|
+
#Helper class for storing data parsed from file maps
|
|
6
|
+
class FileInfo
|
|
7
|
+
|
|
8
|
+
attr_reader :source, :destination
|
|
9
|
+
|
|
10
|
+
def initialize(source, destination, opts = {})
|
|
11
|
+
if(source.nil?)
|
|
12
|
+
raise AppSpecValidationException, 'File needs to have a source'
|
|
13
|
+
elsif (destination.nil?)
|
|
14
|
+
raise AppSpecValidationException, 'File needs to have a destination'
|
|
15
|
+
end
|
|
16
|
+
@source = source
|
|
17
|
+
@destination = destination
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
module InstanceAgent
|
|
2
|
+
module CodeDeployPlugin
|
|
3
|
+
module ApplicationSpecification
|
|
4
|
+
|
|
5
|
+
#Helper Class for storing data parsed from permissions list
|
|
6
|
+
class LinuxPermissionInfo
|
|
7
|
+
|
|
8
|
+
attr_reader :object, :pattern, :except, :type, :owner, :group, :mode, :acls, :context
|
|
9
|
+
|
|
10
|
+
def initialize(object, opts = {})
|
|
11
|
+
object = object.to_s
|
|
12
|
+
if (object.empty?)
|
|
13
|
+
raise AppSpecValidationException, 'Permission needs a object value'
|
|
14
|
+
end
|
|
15
|
+
@object = object
|
|
16
|
+
@pattern = opts[:pattern] || "**"
|
|
17
|
+
@except = opts[:except] || []
|
|
18
|
+
@type = opts[:type] || ["file", "directory"]
|
|
19
|
+
@owner = opts[:owner]
|
|
20
|
+
@group = opts[:group]
|
|
21
|
+
@mode = opts[:mode]
|
|
22
|
+
@acls = opts[:acls]
|
|
23
|
+
@context = opts[:context]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def validate_file_permission()
|
|
27
|
+
if @type.include?("file")
|
|
28
|
+
if !"**".eql?(@pattern)
|
|
29
|
+
raise AppSpecValidationException, "Attempt to use pattern #{@pattern} when assigning permissions to file #{@object}"
|
|
30
|
+
end
|
|
31
|
+
if !@except.empty?
|
|
32
|
+
raise AppSpecValidationException, "Attempt to use except #{@except} when assigning permissions to file #{@object}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def validate_file_acl(object)
|
|
38
|
+
if !@acls.nil?
|
|
39
|
+
default_acl = @acls.get_default_ace
|
|
40
|
+
if !default_acl.nil?
|
|
41
|
+
raise "Attempt to set default acl #{default_acl} on file #{object}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def matches_pattern?(name)
|
|
47
|
+
name = name.chomp(File::SEPARATOR)
|
|
48
|
+
base_object = sanitize_dir_path(@object)
|
|
49
|
+
if !base_object.end_with?(File::SEPARATOR)
|
|
50
|
+
base_object = base_object + File::SEPARATOR
|
|
51
|
+
end
|
|
52
|
+
if name.start_with?(base_object)
|
|
53
|
+
if ("**".eql?(@pattern))
|
|
54
|
+
return true
|
|
55
|
+
end
|
|
56
|
+
rel_name = name[base_object.length..name.length]
|
|
57
|
+
return matches_simple_glob(rel_name, @pattern)
|
|
58
|
+
end
|
|
59
|
+
false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def matches_except?(name)
|
|
63
|
+
name = name.chomp(File::SEPARATOR)
|
|
64
|
+
base_object = sanitize_dir_path(@object)
|
|
65
|
+
if !base_object.end_with?(File::SEPARATOR)
|
|
66
|
+
base_object = base_object + File::SEPARATOR
|
|
67
|
+
end
|
|
68
|
+
if name.start_with?(base_object)
|
|
69
|
+
rel_name = name[base_object.length..name.length]
|
|
70
|
+
@except.each do |item|
|
|
71
|
+
if matches_simple_glob(rel_name, item)
|
|
72
|
+
return true
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
false
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
def matches_simple_glob(name, pattern)
|
|
81
|
+
if name.include?(File::SEPARATOR)
|
|
82
|
+
return false
|
|
83
|
+
end
|
|
84
|
+
options = expand(pattern.chars.entries)
|
|
85
|
+
name.chars.each do |char|
|
|
86
|
+
new_options = []
|
|
87
|
+
options.each do |option|
|
|
88
|
+
if option[0].eql?("*")
|
|
89
|
+
new_options.concat(expand(option))
|
|
90
|
+
elsif option[0].eql?(char)
|
|
91
|
+
option.shift
|
|
92
|
+
new_options.concat(expand(option))
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
options = new_options
|
|
96
|
+
if (options.include?(["*"]))
|
|
97
|
+
return true
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
options.include?([])
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
def expand(option)
|
|
105
|
+
previous_option = nil
|
|
106
|
+
while "*".eql?(option[0]) do
|
|
107
|
+
previous_option = Array.new(option)
|
|
108
|
+
option.shift
|
|
109
|
+
end
|
|
110
|
+
previous_option.nil? ? [option] : [previous_option, option]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
def sanitize_dir_path(path)
|
|
115
|
+
File.expand_path(path)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module InstanceAgent
|
|
2
|
+
module CodeDeployPlugin
|
|
3
|
+
module ApplicationSpecification
|
|
4
|
+
|
|
5
|
+
#Helper Class for storing mode of a file
|
|
6
|
+
class ModeInfo
|
|
7
|
+
|
|
8
|
+
attr_reader :mode
|
|
9
|
+
attr_reader :world, :world_readable, :world_writable, :world_executable
|
|
10
|
+
attr_reader :group, :group_readable, :group_writable, :group_executable
|
|
11
|
+
attr_reader :owner, :owner_readable, :owner_writable, :owner_executable
|
|
12
|
+
attr_reader :setuid, :setgid, :sticky
|
|
13
|
+
|
|
14
|
+
def initialize(mode)
|
|
15
|
+
mode = mode.to_s
|
|
16
|
+
while mode.length < 3 do
|
|
17
|
+
mode = "0" + mode;
|
|
18
|
+
end
|
|
19
|
+
if mode.length > 4
|
|
20
|
+
raise AppSpecValidationException, "permission mode length incorrect: #{mode}"
|
|
21
|
+
end
|
|
22
|
+
mode.each_char do |char|
|
|
23
|
+
if (char.ord < '0'.ord) || (char.ord > '7'.ord)
|
|
24
|
+
raise AppSpecValidationException, "invalid character #{char} in permission mode #{mode}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
@mode = mode
|
|
28
|
+
mode_array = mode.reverse.chars.entries
|
|
29
|
+
|
|
30
|
+
@world = mode_array[0]
|
|
31
|
+
world_bits = to_bits(@world.to_i, 3)
|
|
32
|
+
@world_readable = (world_bits[0] == 1)
|
|
33
|
+
@world_writable = (world_bits[1] == 1)
|
|
34
|
+
@world_executable = (world_bits[2] == 1)
|
|
35
|
+
|
|
36
|
+
@group = mode_array[1]
|
|
37
|
+
group_bits = to_bits(@group.to_i, 3)
|
|
38
|
+
@group_readable = (group_bits[0] == 1)
|
|
39
|
+
@group_writable = (group_bits[1] == 1)
|
|
40
|
+
@group_executable = (group_bits[2] == 1)
|
|
41
|
+
|
|
42
|
+
@owner = mode_array[2]
|
|
43
|
+
owner_bits = to_bits(@owner.to_i, 3)
|
|
44
|
+
@owner_readable = (owner_bits[0] == 1)
|
|
45
|
+
@owner_writable = (owner_bits[1] == 1)
|
|
46
|
+
@owner_executable = (owner_bits[2] == 1)
|
|
47
|
+
|
|
48
|
+
special = (mode_array.length > 3) ? mode_array[3]: '0'
|
|
49
|
+
special_bits = to_bits(special.to_i, 3)
|
|
50
|
+
@setuid = (special_bits[0] == 1)
|
|
51
|
+
@setgid = (special_bits[1] == 1)
|
|
52
|
+
@sticky = (special_bits[2] == 1)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def to_bits(num, min_size)
|
|
56
|
+
bits = Array.new(min_size, 0)
|
|
57
|
+
num_bits = num.to_s(2).split("")
|
|
58
|
+
diff = [0, min_size - num_bits.length].max
|
|
59
|
+
num_bits.map.with_index {|n,i| bits[i+diff] = n.to_i}
|
|
60
|
+
bits
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
module InstanceAgent
|
|
2
|
+
module CodeDeployPlugin
|
|
3
|
+
module ApplicationSpecification
|
|
4
|
+
|
|
5
|
+
#Helper Class for storing the range of a context
|
|
6
|
+
class RangeInfo
|
|
7
|
+
|
|
8
|
+
attr_reader :low_sensitivity, :high_sensitivity, :categories
|
|
9
|
+
|
|
10
|
+
def initialize(range)
|
|
11
|
+
parts = ensure_parts(range, ":")
|
|
12
|
+
sensitivity_parts = ensure_parts(parts[0], "-")
|
|
13
|
+
@low_sensitivity = getSensitivityNumber(sensitivity_parts[0])
|
|
14
|
+
if sensitivity_parts.length == 2
|
|
15
|
+
@high_sensitivity = getSensitivityNumber(sensitivity_parts[1])
|
|
16
|
+
if @high_sensitivity < @low_sensitivity
|
|
17
|
+
raise AppSpecValidationException, "invalid sensitivity range in #{range}"
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
@high_sensitivity = @low_sensitivity
|
|
21
|
+
end
|
|
22
|
+
if parts.length == 2
|
|
23
|
+
@categories = get_category_numbers(parts[1].split(","))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ensure_parts(input, split_on)
|
|
28
|
+
num_parts = 1
|
|
29
|
+
if input.include?(split_on)
|
|
30
|
+
num_parts = 2
|
|
31
|
+
end
|
|
32
|
+
parts = input.split(split_on, 2)
|
|
33
|
+
if parts.length != num_parts
|
|
34
|
+
raise AppSpecValidationException, "invalid range part #{input}"
|
|
35
|
+
end
|
|
36
|
+
parts.each do |part|
|
|
37
|
+
if part.nil? || part.eql?('')
|
|
38
|
+
raise AppSpecValidationException, "invalid range part #{input}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
parts
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def getSensitivityNumber(sensitivity)
|
|
45
|
+
if sensitivity.nil? || sensitivity.length < 2 || !sensitivity.start_with?('s')
|
|
46
|
+
raise AppSpecValidationException, "invalid sensitivity #{sensitivity}"
|
|
47
|
+
end
|
|
48
|
+
s_level = sensitivity.sub('s', '')
|
|
49
|
+
s_level.chars.each do |digit|
|
|
50
|
+
if (digit.ord < '0'.ord) || (digit.ord > '9'.ord)
|
|
51
|
+
raise AppSpecValidationException, "invalid sensitivity #{sensitivity}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
s_level.to_i
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def get_category_number(category)
|
|
58
|
+
if category.nil? || category.length < 2 || !category.start_with?('c')
|
|
59
|
+
raise AppSpecValidationException, "invalid category #{category}"
|
|
60
|
+
end
|
|
61
|
+
c_level = category.sub('c', '')
|
|
62
|
+
c_level.chars.each do |digit|
|
|
63
|
+
if (digit.ord < '0'.ord) || (digit.ord > '9'.ord)
|
|
64
|
+
raise AppSpecValidationException, "invalid category #{category}"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
level = c_level.to_i
|
|
68
|
+
if level > 1023
|
|
69
|
+
raise AppSpecValidationException, "invalid category #{category}"
|
|
70
|
+
end
|
|
71
|
+
level
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def get_category_range(range)
|
|
75
|
+
low = get_category_number(range[0])
|
|
76
|
+
high = get_category_number(range[1])
|
|
77
|
+
if (high < low)
|
|
78
|
+
raise AppSpecValidationException, "invalid category range #{range[0]}.#{range[1]}"
|
|
79
|
+
end
|
|
80
|
+
(low..high).to_a
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def get_category_numbers(parts)
|
|
84
|
+
temp_categories = [];
|
|
85
|
+
parts.each do |part|
|
|
86
|
+
if part.include? "."
|
|
87
|
+
temp_categories.concat get_category_range(ensure_parts(part, "."))
|
|
88
|
+
else
|
|
89
|
+
temp_categories << get_category_number(part)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
if !temp_categories.sort!.uniq!.nil?
|
|
93
|
+
raise AppSpecValidationException, "duplicate categories"
|
|
94
|
+
end
|
|
95
|
+
temp_categories
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# format s#[-s#][:c#[.c#](,c#[.c#])*] (# means a number)
|
|
99
|
+
def get_range
|
|
100
|
+
range = "s" + @low_sensitivity.to_s
|
|
101
|
+
if (@low_sensitivity != @high_sensitivity)
|
|
102
|
+
range = range + "-s" + @high_sensitivity.to_s
|
|
103
|
+
end
|
|
104
|
+
if @categories
|
|
105
|
+
range = range + ":"
|
|
106
|
+
index = 0
|
|
107
|
+
while index < @categories.length
|
|
108
|
+
if (index != 0)
|
|
109
|
+
range = range + ","
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
low = @categories[index]
|
|
113
|
+
low_index = index
|
|
114
|
+
high = @categories[index]
|
|
115
|
+
index += 1
|
|
116
|
+
while (@categories[index] == low + (index - low_index))
|
|
117
|
+
high += 1
|
|
118
|
+
index += 1
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if (low == high)
|
|
122
|
+
range = range + "c" + low.to_s
|
|
123
|
+
else
|
|
124
|
+
range = range + "c" + low.to_s + ".c" + high.to_s
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
range
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|