ridley 0.12.4 → 1.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/Gemfile +1 -1
  2. data/lib/ridley.rb +3 -3
  3. data/lib/ridley/bootstrap_context.rb +100 -0
  4. data/lib/ridley/bootstrap_context/unix.rb +74 -0
  5. data/lib/ridley/bootstrap_context/windows.rb +120 -0
  6. data/lib/ridley/chef_objects/node_object.rb +8 -5
  7. data/lib/ridley/host_commander.rb +207 -0
  8. data/lib/ridley/host_connector.rb +49 -87
  9. data/lib/ridley/host_connector/ssh.rb +153 -39
  10. data/lib/ridley/host_connector/winrm.rb +164 -39
  11. data/lib/ridley/resources/node_resource.rb +52 -56
  12. data/lib/ridley/version.rb +1 -1
  13. data/ridley.gemspec +0 -2
  14. data/spec/spec_helper.rb +4 -4
  15. data/spec/support/chef_server.rb +9 -3
  16. data/spec/unit/ridley/{bootstrap_bindings/unix_template_binding_spec.rb → bootstrap_context/unix_spec.rb} +2 -2
  17. data/spec/unit/ridley/{bootstrap_bindings/windows_template_binding_spec.rb → bootstrap_context/windows_spec.rb} +2 -2
  18. data/spec/unit/ridley/{mixin/bootstrap_binding_spec.rb → bootstrap_context_spec.rb} +2 -6
  19. data/spec/unit/ridley/host_commander_spec.rb +208 -0
  20. data/spec/unit/ridley/host_connector/ssh_spec.rb +37 -31
  21. data/spec/unit/ridley/host_connector/winrm_spec.rb +124 -31
  22. data/spec/unit/ridley/host_connector_spec.rb +23 -147
  23. data/spec/unit/ridley/resources/node_resource_spec.rb +55 -115
  24. metadata +17 -66
  25. data/lib/ridley/bootstrap_bindings.rb +0 -3
  26. data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +0 -108
  27. data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +0 -163
  28. data/lib/ridley/bootstrapper.rb +0 -89
  29. data/lib/ridley/bootstrapper/context.rb +0 -81
  30. data/lib/ridley/host_connector/response_set.rb +0 -98
  31. data/lib/ridley/host_connector/ssh/worker.rb +0 -135
  32. data/lib/ridley/host_connector/winrm/worker.rb +0 -159
  33. data/lib/ridley/log.rb +0 -10
  34. data/lib/ridley/mixin/bootstrap_binding.rb +0 -77
  35. data/spec/unit/ridley/bootstrapper/context_spec.rb +0 -45
  36. data/spec/unit/ridley/bootstrapper_spec.rb +0 -96
  37. data/spec/unit/ridley/host_connector/response_set_spec.rb +0 -112
  38. data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +0 -57
  39. data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +0 -139
@@ -1,159 +0,0 @@
1
- module Ridley
2
- module HostConnector
3
- class WinRM
4
- # @author Kyle Allan <kallan@riotgames.com>
5
- # @api private
6
- class Worker
7
- include Celluloid
8
- include Celluloid::Logger
9
-
10
- # @return [String]
11
- attr_reader :user
12
- # @return [String]
13
- attr_reader :password
14
- # @return [String]
15
- attr_reader :host
16
- # @return [Hash]
17
- attr_reader :options
18
- # @return [String]
19
- attr_reader :winrm_endpoint
20
- # @return [CommandUploader]
21
- attr_reader :command_uploader
22
- # @return [Array]
23
- attr_reader :command_uploaders
24
-
25
- finalizer :finalize_callback
26
-
27
- EMBEDDED_RUBY_PATH = 'C:\opscode\chef\embedded\bin\ruby'.freeze
28
-
29
- # @param host [String]
30
- # the host the worker is going to work on
31
- # @option options [Hash] :winrm
32
- # * :user (String) a user that will login to each node and perform the bootstrap command on (required)
33
- # * :password (String) the password for the user that will perform the bootstrap
34
- # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
35
- def initialize(host, options = {})
36
- options = options.deep_symbolize_keys
37
- @options = options[:winrm] || Hash.new
38
- @host = host
39
- @user = @options[:user]
40
- @password = @options[:password]
41
- @winrm_endpoint = "http://#{host}:#{winrm_port}/wsman"
42
- @command_uploaders = Array.new
43
- end
44
-
45
- def run(command)
46
- response = Ridley::HostConnector::Response.new(host)
47
- command_uploaders << command_uploader = CommandUploader.new(winrm)
48
- command = get_command(command, command_uploader)
49
-
50
- debug "Running WinRM Command: '#{command}' on: '#{host}' as: '#{user}'"
51
-
52
- output = winrm.run_cmd(command) do |stdout, stderr|
53
- if stdout
54
- response.stdout += stdout
55
- info "NODE[#{host}] #{stdout}"
56
- end
57
-
58
- if stderr
59
- response.stderr += stderr unless stderr.nil?
60
- info "NODE[#{host}] #{stdout}"
61
- end
62
- end
63
-
64
- response.exit_code = output[:exitcode]
65
-
66
- case response.exit_code
67
- when 0
68
- debug "Successfully ran WinRM command on: '#{host}' as: '#{user}'"
69
- [ :ok, response ]
70
- else
71
- error "Successfully ran WinRM command on: '#{host}' as: '#{user}', but it failed"
72
- error response.stdout
73
- [ :error, response ]
74
- end
75
- rescue => e
76
- error "Failed to run WinRM command on: '#{host}' as: '#{user}'"
77
- error "#{e.class}: #{e.message}"
78
- response.exit_code = -1
79
- response.stderr = e.message
80
- [ :error, response ]
81
- end
82
-
83
- # @return [WinRM::WinRMWebService]
84
- def winrm
85
- @winrm_client ||= begin
86
- require 'active_support/core_ext/kernel/reporting'
87
- # Silencing warnings because not all versions of GSSAPI support all of the GSSAPI methods
88
- # the gssapi gem attempts to attach to and these warnings are dumped to STDERR.
89
- silence_warnings do
90
- require 'winrm'
91
- end
92
-
93
- client = ::WinRM::WinRMWebService.new(winrm_endpoint, :plaintext,
94
- user: user, pass: password, disable_sspi: true, basic_auth_only: true)
95
- client.set_timeout(6000)
96
- client
97
- end
98
- end
99
-
100
- # @return [Fixnum]
101
- def winrm_port
102
- options[:port] || Ridley::HostConnector::DEFAULT_WINRM_PORT
103
- end
104
-
105
- # Returns the command if it does not break the WinRM command length
106
- # limit. Otherwise, we return an execution of the command as a batch file.
107
- #
108
- # @param command [String]
109
- #
110
- # @return [String]
111
- def get_command(command, command_uploader)
112
- if command.length < CommandUploader::CHUNK_LIMIT
113
- command
114
- else
115
- debug "Detected a command that was longer than #{CommandUploader::CHUNK_LIMIT} characters, \
116
- uploading command as a file to the host."
117
- command_uploader.upload(command)
118
- command_uploader.command
119
- end
120
- end
121
-
122
- # Executes a chef-client run on the nodes
123
- #
124
- # @return [#run]
125
- def chef_client
126
- run("chef-client")
127
- end
128
-
129
- # Writes the given encrypted data bag secret to the node
130
- #
131
- # @param [String] secret
132
- # your organization's encrypted data bag secret
133
- #
134
- # @return [#run]
135
- def put_secret(secret)
136
- command = "echo #{secret} > C:\\chef\\encrypted_data_bag_secret"
137
- run(command)
138
- end
139
-
140
- # Executes a provided Ruby script in the embedded Ruby installation
141
- #
142
- # @param [Array<String>] command_lines
143
- # An Array of lines of the command to be executed
144
- #
145
- # @return [#run]
146
- def ruby_script(command_lines)
147
- command = "#{EMBEDDED_RUBY_PATH} -e \"#{command_lines.join(';')}\""
148
- run(command)
149
- end
150
-
151
- private
152
-
153
- def finalize_callback
154
- command_uploaders.map(&:cleanup)
155
- end
156
- end
157
- end
158
- end
159
- end
data/lib/ridley/log.rb DELETED
@@ -1,10 +0,0 @@
1
- require 'mixlib/log'
2
-
3
- module Ridley
4
- # @author Jamie Winsor <reset@riotgames.com>
5
- class Log
6
- extend Mixlib::Log
7
-
8
- init
9
- end
10
- end
@@ -1,77 +0,0 @@
1
- require 'erubis'
2
-
3
- module Ridley
4
- module BootstrapBinding
5
- module ClassMethods
6
- def validate_options(options = {})
7
- if options[:server_url].nil?
8
- raise Errors::ArgumentError, "A server_url is required for bootstrapping"
9
- end
10
-
11
- if options[:validator_path].nil?
12
- raise Errors::ArgumentError, "A path to a validator is required for bootstrapping"
13
- end
14
- end
15
-
16
- # A hash of default options to be used in the Context initializer
17
- #
18
- # @return [Hash]
19
- def default_options
20
- @default_options ||= {
21
- validator_client: "chef-validator",
22
- attributes: Hash.new,
23
- run_list: Array.new,
24
- environment: "_default",
25
- sudo: true,
26
- hints: Hash.new
27
- }
28
- end
29
- end
30
-
31
- class << self
32
- def included(base)
33
- base.extend(ClassMethods)
34
- end
35
- end
36
-
37
- attr_reader :template_file
38
- attr_reader :bootstrap_proxy
39
- attr_reader :chef_version
40
- attr_reader :default_options
41
- attr_reader :validator_path
42
- attr_reader :encrypted_data_bag_secret
43
- attr_reader :server_url
44
- attr_reader :validator_client
45
- attr_reader :node_name
46
- attr_reader :attributes
47
- attr_reader :run_list
48
- attr_reader :environment
49
-
50
- # @return [Pathname]
51
- def templates_path
52
- Ridley.root.join('bootstrappers')
53
- end
54
-
55
- # @return [String]
56
- def first_boot
57
- JSON.fast_generate(attributes.merge(run_list: run_list))
58
- end
59
-
60
- # The validation key to create a new client for the node
61
- #
62
- # @raise [Ridley::Errors::ValidatorNotFound]
63
- #
64
- # @return [String]
65
- def validation_key
66
- IO.read(File.expand_path(validator_path)).chomp
67
- rescue Errno::ENOENT
68
- raise Errors::ValidatorNotFound, "Error bootstrapping: Validator not found at '#{validator_path}'"
69
- end
70
-
71
- # @return [Erubis::Eruby]
72
- def template
73
- Erubis::Eruby.new(IO.read(template_file).chomp)
74
- end
75
-
76
- end
77
- end
@@ -1,45 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Ridley::Bootstrapper::Context do
4
- let(:host) { "reset.riotgames.com" }
5
-
6
- let(:options) do
7
- {
8
- server_url: "https://api.opscode.com/organizations/vialstudios",
9
- validator_client: "chef-validator",
10
- validator_path: fixtures_path.join("reset.pem").to_s,
11
- encrypted_data_bag_secret: File.read(fixtures_path.join("reset.pem"))
12
- }
13
- end
14
-
15
- describe "ClassMethods" do
16
- subject { Ridley::Bootstrapper::Context }
17
-
18
- describe "::create" do
19
- context "when the best connection is SSH" do
20
- it "sets template_binding to a Ridley::UnixTemplateBinding" do
21
- Ridley::HostConnector.stub(:best_connector_for).and_return(Ridley::HostConnector::SSH)
22
- context = subject.create(host, options)
23
- context.template_binding.should be_a(Ridley::UnixTemplateBinding)
24
- end
25
- end
26
-
27
- context "when the best connection is WinRM" do
28
- it "sets template_binding to a Ridley::WindowsTemplateBinding" do
29
- Ridley::HostConnector.stub(:best_connector_for).and_return(Ridley::HostConnector::WinRM)
30
- context = subject.create(host, options)
31
- context.template_binding.should be_a(Ridley::WindowsTemplateBinding)
32
- end
33
- end
34
-
35
- context "when there is no good connection option" do
36
- it "raises an error" do
37
- Ridley::HostConnector.stub(:best_connector_for).and_return(nil)
38
- expect {
39
- context = subject.create(host, options)
40
- }.to raise_error(Ridley::Errors::HostConnectionError)
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,96 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Ridley::Bootstrapper do
4
- let(:nodes) do
5
- [
6
- "33.33.33.10"
7
- ]
8
- end
9
-
10
- let(:options) do
11
- {
12
- ssh_user: "vagrant",
13
- ssh_password: "vagrant",
14
- server_url: "https://api.opscode.com/organizations/vialstudios",
15
- validator_client: "vialstudios-validator",
16
- validator_path: fixtures_path.join("reset.pem").to_s,
17
- encrypted_data_bag_secret: File.read(fixtures_path.join("reset.pem"))
18
- }
19
- end
20
-
21
- before(:each) { Ridley::HostConnector.stub(:best_connector_for).and_return(Ridley::HostConnector::SSH) }
22
-
23
- describe "ClassMethods" do
24
- subject { Ridley::Bootstrapper }
25
-
26
- describe "::new" do
27
- context "given a single string for nodes" do
28
- before(:each) do
29
- @obj = subject.new("33.33.33.10", options)
30
- end
31
-
32
- it "has one node" do
33
- @obj.hosts.should have(1).item
34
- end
35
-
36
- it "has one context" do
37
- @obj.contexts.should have(1).item
38
- end
39
- end
40
-
41
- context "given an an array of strings nodes" do
42
- before(:each) do
43
- @obj = subject.new(["33.33.33.10", "33.33.33.11"], options)
44
- end
45
-
46
- it "has a host for each item given" do
47
- @obj.hosts.should have(2).items
48
- end
49
-
50
- it "has a context for each item given" do
51
- @obj.contexts.should have(2).items
52
- end
53
- end
54
- end
55
- end
56
-
57
- subject { Ridley::Bootstrapper.new(nodes, options) }
58
-
59
- describe "#hosts" do
60
- it "returns an array of strings" do
61
- subject.hosts.should be_a(Array)
62
- subject.hosts.should each be_a(String)
63
- end
64
- end
65
-
66
- describe "#contexts" do
67
- before do
68
- Ridley::Bootstrapper::Context.stub(:create).and_return(double)
69
- end
70
-
71
- it "creates a new context for each host" do
72
- Ridley::Bootstrapper::Context.should_receive(:create).exactly(nodes.length).times
73
- subject.contexts
74
- end
75
-
76
- it "contains a item for each host" do
77
- subject.contexts.should have(nodes.length).items
78
- end
79
-
80
- context "when a host is unreachable" do
81
- before do
82
- Ridley::Bootstrapper::Context.stub(:create).and_raise(Ridley::Errors::HostConnectionError)
83
- end
84
-
85
- it "raises a HostConnectionError" do
86
- expect {
87
- subject.contexts
88
- }.to raise_error(Ridley::Errors::HostConnectionError)
89
- end
90
- end
91
- end
92
-
93
- describe "#run" do
94
- pending
95
- end
96
- end
@@ -1,112 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Ridley::HostConnector::ResponseSet do
4
- describe "ClassMethods" do
5
- subject { described_class }
6
-
7
- describe "::merge!" do
8
- let(:target) { Ridley::HostConnector::ResponseSet.new }
9
- let(:other) { Ridley::HostConnector::ResponseSet.new }
10
-
11
- before(:each) do
12
- other.add_response(Ridley::HostConnector::Response.new('host.local'))
13
- end
14
-
15
- it "returns the mutated target" do
16
- result = subject.merge!(target, other)
17
-
18
- result.should eql(target)
19
- result.should have(1).item
20
- end
21
- end
22
- end
23
-
24
- subject { described_class.new }
25
-
26
- describe "#add_response" do
27
- it "accepts an array of responses" do
28
- responses = [
29
- Ridley::HostConnector::Response.new("one.riotgames.com"),
30
- Ridley::HostConnector::Response.new("two.riotgames.com")
31
- ]
32
- subject.add_response(responses)
33
-
34
- subject.responses.should have(2).items
35
- end
36
-
37
- it "accepts a single response" do
38
- response = Ridley::HostConnector::Response.new("one.riotgames.com")
39
- subject.add_response(response)
40
-
41
- subject.responses.should have(1).item
42
- end
43
- end
44
-
45
- describe "#responses" do
46
- it "returns an array of Ridley::HostConnector::Response objects including both failures and successes" do
47
- responses = [
48
- double('success', error?: false),
49
- double('failure', error?: true)
50
- ]
51
- subject.add_response(responses)
52
-
53
- subject.responses.should have(2).items
54
- end
55
- end
56
-
57
- describe "#successes" do
58
- it "returns an array of Ridley::HostConnector::Response objects only including the successes" do
59
- responses = [
60
- double('success', error?: false),
61
- double('failure', error?: true)
62
- ]
63
- subject.add_response(responses)
64
-
65
- subject.successes.should have(1).item
66
- end
67
- end
68
-
69
- describe "#failures" do
70
- it "returns an array of Ridley::HostConnector::Response objects only including the failures" do
71
- responses = [
72
- double('success', error?: false),
73
- double('failure', error?: true)
74
- ]
75
- subject.add_response(responses)
76
-
77
- subject.failures.should have(1).item
78
- end
79
- end
80
-
81
- describe "#merge" do
82
- let(:target) { Ridley::HostConnector::ResponseSet.new }
83
- let(:other) { Ridley::HostConnector::ResponseSet.new }
84
-
85
- before(:each) do
86
- other.add_response(Ridley::HostConnector::Response.new('host.local'))
87
- end
88
-
89
- it "returns a new Ridley::HostConnector::ResponseSet object" do
90
- result = target.merge(other)
91
-
92
- result.should have(1).item
93
- target.should have(0).items
94
- end
95
- end
96
-
97
- describe "#merge!" do
98
- let(:target) { Ridley::HostConnector::ResponseSet.new }
99
- let(:other) { Ridley::HostConnector::ResponseSet.new }
100
-
101
- before(:each) do
102
- other.add_response(Ridley::HostConnector::Response.new('host.local'))
103
- end
104
-
105
- it "returns the mutated target" do
106
- result = target.merge!(other)
107
-
108
- result.should have(1).item
109
- target.should have(1).item
110
- end
111
- end
112
- end