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.
Files changed (84) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGES.md +3 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +177 -0
  5. data/NOTICE +2 -0
  6. data/README.md +16 -0
  7. data/aws-codedeploy-agent.gemspec +39 -0
  8. data/bin/codedeploy-agent +78 -0
  9. data/bin/codedeploy-install +15 -0
  10. data/bin/codedeploy-uninstall +13 -0
  11. data/certs/host-agent-deployment-signer-ca-chain.pem +76 -0
  12. data/conf/codedeployagent.yml +9 -0
  13. data/init.d/codedeploy-agent +61 -0
  14. data/lib/core_ext.rb +71 -0
  15. data/lib/instance_agent.rb +35 -0
  16. data/lib/instance_agent/agent/base.rb +34 -0
  17. data/lib/instance_agent/codedeploy_plugin/application_specification/ace_info.rb +133 -0
  18. data/lib/instance_agent/codedeploy_plugin/application_specification/acl_info.rb +163 -0
  19. data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb +142 -0
  20. data/lib/instance_agent/codedeploy_plugin/application_specification/context_info.rb +23 -0
  21. data/lib/instance_agent/codedeploy_plugin/application_specification/file_info.rb +23 -0
  22. data/lib/instance_agent/codedeploy_plugin/application_specification/linux_permission_info.rb +121 -0
  23. data/lib/instance_agent/codedeploy_plugin/application_specification/mode_info.rb +66 -0
  24. data/lib/instance_agent/codedeploy_plugin/application_specification/range_info.rb +134 -0
  25. data/lib/instance_agent/codedeploy_plugin/application_specification/script_info.rb +27 -0
  26. data/lib/instance_agent/codedeploy_plugin/codedeploy_control.rb +72 -0
  27. data/lib/instance_agent/codedeploy_plugin/command_executor.rb +357 -0
  28. data/lib/instance_agent/codedeploy_plugin/command_poller.rb +146 -0
  29. data/lib/instance_agent/codedeploy_plugin/deployment_specification.rb +150 -0
  30. data/lib/instance_agent/codedeploy_plugin/hook_executor.rb +206 -0
  31. data/lib/instance_agent/codedeploy_plugin/install_instruction.rb +374 -0
  32. data/lib/instance_agent/codedeploy_plugin/installer.rb +143 -0
  33. data/lib/instance_agent/codedeploy_plugin/request_helper.rb +28 -0
  34. data/lib/instance_agent/config.rb +43 -0
  35. data/lib/instance_agent/log.rb +3 -0
  36. data/lib/instance_agent/platform.rb +17 -0
  37. data/lib/instance_agent/platform/linux_util.rb +57 -0
  38. data/lib/instance_agent/runner/child.rb +57 -0
  39. data/lib/instance_agent/runner/master.rb +103 -0
  40. data/lib/instance_metadata.rb +47 -0
  41. data/test/certificate_helper.rb +120 -0
  42. data/test/helpers/instance_agent_helper.rb +25 -0
  43. data/test/instance_agent/agent/base_test.rb +49 -0
  44. data/test/instance_agent/codedeploy_plugin/application_specification_test.rb +1710 -0
  45. data/test/instance_agent/codedeploy_plugin/codedeploy_control_test.rb +51 -0
  46. data/test/instance_agent/codedeploy_plugin/command_executor_test.rb +513 -0
  47. data/test/instance_agent/codedeploy_plugin/command_poller_test.rb +459 -0
  48. data/test/instance_agent/codedeploy_plugin/deployment_specification_test.rb +335 -0
  49. data/test/instance_agent/codedeploy_plugin/hook_executor_test.rb +250 -0
  50. data/test/instance_agent/codedeploy_plugin/install_instruction_test.rb +566 -0
  51. data/test/instance_agent/codedeploy_plugin/installer_test.rb +519 -0
  52. data/test/instance_agent/codedeploy_plugin/request_helper_test.rb +37 -0
  53. data/test/instance_agent/config_test.rb +64 -0
  54. data/test/instance_agent/runner/child_test.rb +87 -0
  55. data/test/instance_metadata_test.rb +97 -0
  56. data/test/test_helper.rb +16 -0
  57. data/vendor/gems/.codedeploy-commands-1.0.0.created.rid +1 -0
  58. data/vendor/gems/codedeploy-commands/apis/CodeDeployCommand.api.json +372 -0
  59. data/vendor/gems/codedeploy-commands/codedeploy-commands-1.0.0.gemspec +28 -0
  60. data/vendor/gems/codedeploy-commands/lib/aws/codedeploy_commands.rb +18 -0
  61. data/vendor/gems/codedeploy-commands/lib/aws/plugins/certificate_authority.rb +12 -0
  62. data/vendor/gems/codedeploy-commands/lib/aws/plugins/deploy_control_endpoint.rb +22 -0
  63. data/vendor/gems/process_manager/README.md +1 -0
  64. data/vendor/gems/process_manager/lib/blank.rb +153 -0
  65. data/vendor/gems/process_manager/lib/core_ext.rb +73 -0
  66. data/vendor/gems/process_manager/lib/process_manager.rb +49 -0
  67. data/vendor/gems/process_manager/lib/process_manager/child.rb +119 -0
  68. data/vendor/gems/process_manager/lib/process_manager/config.rb +112 -0
  69. data/vendor/gems/process_manager/lib/process_manager/log.rb +107 -0
  70. data/vendor/gems/process_manager/lib/process_manager/master.rb +322 -0
  71. data/vendor/gems/process_manager/process_manager-0.0.13.gemspec +42 -0
  72. data/vendor/specifications/aws-sdk-core-2.0.5.gemspec +39 -0
  73. data/vendor/specifications/builder-3.2.2.gemspec +29 -0
  74. data/vendor/specifications/codedeploy-commands-1.0.0.gemspec +28 -0
  75. data/vendor/specifications/gli-2.5.6.gemspec +51 -0
  76. data/vendor/specifications/jamespath-0.5.1.gemspec +35 -0
  77. data/vendor/specifications/little-plugger-1.1.3.gemspec +32 -0
  78. data/vendor/specifications/logging-1.8.1.gemspec +44 -0
  79. data/vendor/specifications/multi_json-1.7.7.gemspec +30 -0
  80. data/vendor/specifications/multi_json-1.8.4.gemspec +30 -0
  81. data/vendor/specifications/multi_xml-0.5.5.gemspec +30 -0
  82. data/vendor/specifications/process_manager-0.0.13.gemspec +42 -0
  83. data/vendor/specifications/simple_pid-0.2.1.gemspec +28 -0
  84. metadata +377 -0
@@ -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