knife-server 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cane +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/.travis.yml +12 -8
- data/CHANGELOG.md +32 -1
- data/Gemfile +9 -4
- data/Guardfile +28 -0
- data/README.md +28 -5
- data/Rakefile +31 -10
- data/knife-server.gemspec +18 -8
- data/lib/chef/knife/bootstrap/_omnibus.sh +63 -10
- data/lib/chef/knife/bootstrap/chef10/rhel.erb +2 -0
- data/lib/chef/knife/bootstrap/chef11/omnibus.erb +4 -1
- data/lib/chef/knife/bootstrap/chef11/rhel.erb +2 -0
- data/lib/chef/knife/server_backup.rb +24 -10
- data/lib/chef/knife/server_bootstrap_base.rb +68 -23
- data/lib/chef/knife/server_bootstrap_ec2.rb +33 -20
- data/lib/chef/knife/server_bootstrap_linode.rb +20 -13
- data/lib/chef/knife/server_bootstrap_openstack.rb +128 -0
- data/lib/chef/knife/server_bootstrap_standalone.rb +28 -16
- data/lib/chef/knife/server_restore.rb +23 -9
- data/lib/knife-server.rb +1 -0
- data/lib/knife/server/credentials.rb +78 -42
- data/lib/knife/server/ec2_security_group.rb +24 -21
- data/lib/knife/server/ssh.rb +54 -18
- data/lib/knife/server/version.rb +2 -1
- data/spec/chef/knife/server_backup_spec.rb +58 -44
- data/spec/chef/knife/server_bootstrap_ec2_spec.rb +108 -80
- data/spec/chef/knife/server_bootstrap_linode_spec.rb +93 -64
- data/spec/chef/knife/server_bootstrap_openstack_spec.rb +305 -0
- data/spec/chef/knife/server_bootstrap_standalone_spec.rb +113 -76
- data/spec/chef/knife/server_restore_spec.rb +38 -37
- data/spec/knife/server/credientials_spec.rb +248 -51
- data/spec/knife/server/ec2_security_group_spec.rb +76 -68
- data/spec/knife/server/ssh_spec.rb +138 -22
- metadata +107 -31
@@ -22,6 +22,7 @@ set -e
|
|
22
22
|
export hostname="<%= @config[:chef_node_name] %>"
|
23
23
|
export version="<%= @config[:bootstrap_version] %>"
|
24
24
|
export prerelease="<%= @config[:prerelease] == true %>"
|
25
|
+
export url="<%= @chef_config[:knife][:server_package_url] %>"
|
25
26
|
export webui_enable="<%= @chef_config[:knife][:webui_enable] == true %>"
|
26
27
|
export webui_password="<%= ENV['WEBUI_PASSWORD'] %>"
|
27
28
|
export amqp_password="<%= ENV['AMQP_PASSWORD'] %>"
|
@@ -55,9 +56,11 @@ tmp_dir=$(mktemp -d -t tmp.XXXXXXXX || echo "/tmp")
|
|
55
56
|
set_hostname_for_${platform}
|
56
57
|
download_package
|
57
58
|
install_package
|
59
|
+
detect_info
|
60
|
+
patch_knife_code
|
58
61
|
prepare_chef_server_rb
|
59
|
-
symlink_binaries
|
60
62
|
reconfigure_chef_server
|
63
|
+
symlink_binaries
|
61
64
|
if [ ! -n "$no_test"]
|
62
65
|
then
|
63
66
|
test_chef_server
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
1
2
|
#
|
2
3
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
3
4
|
# Copyright:: Copyright (c) 2012 Fletcher Nichol
|
@@ -16,16 +17,17 @@
|
|
16
17
|
# limitations under the License.
|
17
18
|
#
|
18
19
|
|
19
|
-
require
|
20
|
-
require
|
20
|
+
require "chef/knife"
|
21
|
+
require "chef/node"
|
21
22
|
|
22
23
|
class Chef
|
23
24
|
class Knife
|
25
|
+
# Backs up a Chef server component.
|
24
26
|
class ServerBackup < Knife
|
25
27
|
|
26
28
|
deps do
|
27
|
-
require
|
28
|
-
require
|
29
|
+
require "fileutils"
|
30
|
+
require "uri"
|
29
31
|
end
|
30
32
|
|
31
33
|
banner "knife server backup COMPONENT[ COMPONENT ...] (options)"
|
@@ -60,10 +62,22 @@ class Chef
|
|
60
62
|
private
|
61
63
|
|
62
64
|
COMPONENTS = {
|
63
|
-
"nodes" => {
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
"nodes" => {
|
66
|
+
:singular => "node",
|
67
|
+
:klass => Chef::Node
|
68
|
+
},
|
69
|
+
"roles" => {
|
70
|
+
:singular => "role",
|
71
|
+
:klass => Chef::Role
|
72
|
+
},
|
73
|
+
"environments" => {
|
74
|
+
:singular => "environment",
|
75
|
+
:klass => Chef::Environment
|
76
|
+
},
|
77
|
+
"data_bags" => {
|
78
|
+
:singular => "data_bag",
|
79
|
+
:klass => Chef::DataBag
|
80
|
+
}
|
67
81
|
}
|
68
82
|
|
69
83
|
def validate!
|
@@ -80,7 +94,7 @@ class Chef
|
|
80
94
|
ui.msg "Creating #{c[:singular]} backups in #{dir_path}"
|
81
95
|
FileUtils.mkdir_p(dir_path)
|
82
96
|
|
83
|
-
Array(c[:klass].list).each do |name,
|
97
|
+
Array(c[:klass].list).each do |name, _url|
|
84
98
|
next if component == "environments" && name == "_default"
|
85
99
|
|
86
100
|
case component
|
@@ -108,7 +122,7 @@ class Chef
|
|
108
122
|
item_path = ::File.join(dir_path, name)
|
109
123
|
FileUtils.mkdir_p(item_path)
|
110
124
|
|
111
|
-
Array(c[:klass].load(name)).each do |item_name,
|
125
|
+
Array(c[:klass].load(name)).each do |item_name, _url|
|
112
126
|
obj = Chef::DataBagItem.load(name, item_name)
|
113
127
|
ui.msg "Backing up #{c[:singular]}[#{name}][#{item_name}]"
|
114
128
|
::File.open(::File.join(item_path, "#{item_name}.json"), "wb") do |f|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
1
2
|
#
|
2
3
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
3
4
|
# Copyright:: Copyright (c) 2012 Fletcher Nichol
|
@@ -16,35 +17,39 @@
|
|
16
17
|
# limitations under the License.
|
17
18
|
#
|
18
19
|
|
19
|
-
require
|
20
|
+
require "chef/knife"
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Knife
|
24
|
+
# Common behavior for server bootstrapping.
|
23
25
|
module ServerBootstrapBase
|
24
26
|
|
25
|
-
def self.included(included_class)
|
27
|
+
def self.included(included_class) # rubocop:disable Metrics/MethodLength
|
26
28
|
included_class.class_eval do
|
27
29
|
|
28
30
|
deps do
|
29
|
-
require
|
30
|
-
require
|
31
|
+
require "chef/knife/ssh"
|
32
|
+
require "net/ssh"
|
31
33
|
end
|
32
34
|
|
33
35
|
option :platform,
|
34
36
|
:short => "-P PLATFORM",
|
35
37
|
:long => "--platform PLATFORM",
|
36
|
-
:description => "The platform type that will be bootstrapped
|
38
|
+
:description => "The platform type that will be bootstrapped, "\
|
39
|
+
"default is 'omnibus'",
|
37
40
|
:default => "omnibus"
|
38
41
|
|
39
42
|
option :distro,
|
40
43
|
:short => "-d DISTRO",
|
41
44
|
:long => "--distro DISTRO",
|
42
|
-
:description => "Bootstrap a distro using a template
|
45
|
+
:description => "Bootstrap a distro using a template, " \
|
46
|
+
"default is 'chef11/omnibus'"
|
43
47
|
|
44
48
|
option :bootstrap_version,
|
45
49
|
:long => "--bootstrap-version VERSION",
|
46
|
-
:description => "The version of Chef Server to install,
|
47
|
-
|
50
|
+
:description => "The version of Chef Server to install, " \
|
51
|
+
"default is latest release",
|
52
|
+
:proc => proc { |v| Chef::Config[:knife][:bootstrap_version] = v },
|
48
53
|
:default => nil
|
49
54
|
|
50
55
|
option :prerelease,
|
@@ -53,13 +58,15 @@ class Chef
|
|
53
58
|
|
54
59
|
option :webui_enable,
|
55
60
|
:long => "--[no-]webui-enable",
|
56
|
-
:description => "Whether or not to enable the webui,
|
57
|
-
|
61
|
+
:description => "Whether or not to enable the webui, " \
|
62
|
+
"default is false",
|
63
|
+
:proc => proc { |v| Chef::Config[:knife][:webui_enable] = v },
|
58
64
|
:default => false
|
59
65
|
|
60
66
|
option :webui_password,
|
61
67
|
:long => "--webui-password SECRET",
|
62
|
-
:description => "Initial password for WebUI admin account,
|
68
|
+
:description => "Initial password for WebUI admin account, " \
|
69
|
+
"default is 'chefchef'",
|
63
70
|
:default => "chefchef"
|
64
71
|
|
65
72
|
option :amqp_password,
|
@@ -70,19 +77,47 @@ class Chef
|
|
70
77
|
option :log_level,
|
71
78
|
:short => "-l LEVEL",
|
72
79
|
:long => "--log-level LEVEL",
|
73
|
-
:description => "Set the log level
|
74
|
-
|
80
|
+
:description => "Set the log level " \
|
81
|
+
"(debug, info, warn, error, fatal), default is error",
|
82
|
+
:proc => proc { |v| Chef::Config[:knife][:log_level] = v.to_sym },
|
75
83
|
:default => :error
|
76
84
|
|
77
85
|
option :no_test,
|
78
86
|
:short => "-n",
|
79
87
|
:long => "--no-test",
|
80
|
-
:description => "Do not run opscode pedant as a part of the
|
88
|
+
:description => "Do not run opscode pedant as a part of the " \
|
89
|
+
"omnibus installation"
|
90
|
+
|
91
|
+
option :url,
|
92
|
+
:long => "--url URL",
|
93
|
+
:description => "URL to specfic package release",
|
94
|
+
:proc => proc { |u| Chef::Config[:knife][:server_package_url] = u }
|
81
95
|
end
|
82
96
|
end
|
83
97
|
|
98
|
+
def run
|
99
|
+
validate!
|
100
|
+
end
|
101
|
+
|
84
102
|
private
|
85
103
|
|
104
|
+
def validate!
|
105
|
+
knife_fail = "You did not set {{KEY}} in your knife.rb, which is a " \
|
106
|
+
"required setting. Please generate an initial knife.rb or read " \
|
107
|
+
"the setup instructions at http://fnichol.github.io/knife-server/"
|
108
|
+
|
109
|
+
# rubocop:disable Style/DeprecatedHashMethods
|
110
|
+
if Chef::Config[:node_name].nil?
|
111
|
+
ui.error knife_fail.gsub(/{{KEY}}/, "node_name")
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
if Chef::Config[:client_key].nil?
|
115
|
+
ui.error knife_fail.gsub(/{{KEY}}/, "client_key")
|
116
|
+
exit 1
|
117
|
+
end
|
118
|
+
# rubocop:enable Style/DeprecatedHashMethods
|
119
|
+
end
|
120
|
+
|
86
121
|
def fetch_validation_key
|
87
122
|
credentials_client.install_validation_key
|
88
123
|
end
|
@@ -100,7 +135,7 @@ class Chef
|
|
100
135
|
config_val(:platform) == "auto"
|
101
136
|
end
|
102
137
|
|
103
|
-
def distro_auto_map(platform,
|
138
|
+
def distro_auto_map(platform, _platform_version)
|
104
139
|
# NOTE this logic is shared with chef/knife/bootstrap/auto.sh, which is
|
105
140
|
# run on the server side.
|
106
141
|
# XXX we don't actually use the platform_version stuff, just included
|
@@ -120,7 +155,7 @@ class Chef
|
|
120
155
|
"suse"
|
121
156
|
end
|
122
157
|
|
123
|
-
|
158
|
+
construct_distro(normal)
|
124
159
|
end
|
125
160
|
|
126
161
|
def construct_distro(platform)
|
@@ -136,7 +171,8 @@ class Chef
|
|
136
171
|
def bootstrap_distro
|
137
172
|
return config_val(:distro) if config_val(:distro)
|
138
173
|
return determine_platform if config_val(:platform) == "auto"
|
139
|
-
|
174
|
+
|
175
|
+
construct_distro(config_val(:platform))
|
140
176
|
end
|
141
177
|
|
142
178
|
def credentials_client
|
@@ -149,23 +185,32 @@ class Chef
|
|
149
185
|
def determine_platform
|
150
186
|
return nil unless bootstrap_auto?
|
151
187
|
|
152
|
-
script = File.binread(
|
188
|
+
script = File.binread(
|
189
|
+
File.expand_path("bootstrap/auto.sh", File.dirname(__FILE__))
|
190
|
+
)
|
153
191
|
|
154
192
|
# result is expected to be two lines, first being the platform name,
|
155
193
|
# second being the platform version.
|
156
194
|
result, exit_status = ssh_connection.run_script(script)
|
157
195
|
|
158
|
-
if exit_status != 0
|
159
|
-
raise "Could not determine the OS running the target for
|
196
|
+
if exit_status != 0 || !result || result.strip.empty?
|
197
|
+
raise "Could not determine the OS running the target for " \
|
198
|
+
"the chef server. Please specify --platform."
|
160
199
|
end
|
161
200
|
|
162
|
-
|
201
|
+
distro_auto_map(*result.split(/\n/).compact[0..1])
|
163
202
|
end
|
164
203
|
|
165
204
|
def config_val(key)
|
166
205
|
key = key.to_sym
|
167
|
-
|
168
|
-
config
|
206
|
+
case
|
207
|
+
when !config[key].nil?
|
208
|
+
config[key]
|
209
|
+
when !Chef::Config[:knife][key].nil?
|
210
|
+
Chef::Config[:knife][key]
|
211
|
+
else
|
212
|
+
options[key] && options[key][:default]
|
213
|
+
end
|
169
214
|
end
|
170
215
|
end
|
171
216
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
1
2
|
#
|
2
3
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
3
4
|
# Copyright:: Copyright (c) 2012 Fletcher Nichol
|
@@ -16,10 +17,11 @@
|
|
16
17
|
# limitations under the License.
|
17
18
|
#
|
18
19
|
|
19
|
-
require
|
20
|
+
require "chef/knife/server_bootstrap_base"
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Knife
|
24
|
+
# Provisions an EC2 instance and sets up an Open Source Chef Server.
|
23
25
|
class ServerBootstrapEc2 < Knife
|
24
26
|
|
25
27
|
banner "knife server bootstrap ec2 (options)"
|
@@ -27,18 +29,18 @@ class Chef
|
|
27
29
|
include Knife::ServerBootstrapBase
|
28
30
|
|
29
31
|
deps do
|
30
|
-
require
|
31
|
-
require
|
32
|
-
require
|
32
|
+
require "knife/server/ssh"
|
33
|
+
require "knife/server/credentials"
|
34
|
+
require "knife/server/ec2_security_group"
|
33
35
|
|
34
36
|
begin
|
35
|
-
require
|
36
|
-
require
|
37
|
+
require "chef/knife/ec2_server_create"
|
38
|
+
require "fog"
|
37
39
|
Chef::Knife::Ec2ServerCreate.load_deps
|
38
40
|
|
39
|
-
current_options =
|
41
|
+
current_options = options
|
40
42
|
self.options = Chef::Knife::Ec2ServerCreate.options.dup
|
41
|
-
|
43
|
+
options.merge!(current_options)
|
42
44
|
rescue LoadError => ex
|
43
45
|
ui.error [
|
44
46
|
"Knife plugin knife-ec2 could not be loaded.",
|
@@ -55,10 +57,10 @@ class Chef
|
|
55
57
|
:long => "--groups X,Y,Z",
|
56
58
|
:description => "The security groups for this server",
|
57
59
|
:default => ["infrastructure"],
|
58
|
-
:proc =>
|
60
|
+
:proc => proc { |groups| groups.split(",") }
|
59
61
|
|
60
62
|
def run
|
61
|
-
|
63
|
+
super
|
62
64
|
config_security_group
|
63
65
|
ec2_bootstrap.run
|
64
66
|
fetch_validation_key
|
@@ -67,12 +69,13 @@ class Chef
|
|
67
69
|
end
|
68
70
|
|
69
71
|
def ec2_bootstrap
|
70
|
-
|
71
|
-
ENV['AMQP_PASSWORD'] = config_val(:amqp_password)
|
72
|
-
ENV['NO_TEST'] = "1" if config[:no_test]
|
72
|
+
setup_environment
|
73
73
|
bootstrap = Chef::Knife::Ec2ServerCreate.new
|
74
74
|
Chef::Knife::Ec2ServerCreate.options.keys.each do |attr|
|
75
|
-
|
75
|
+
val = config_val(attr)
|
76
|
+
next if val.nil?
|
77
|
+
|
78
|
+
bootstrap.config[attr] = val
|
76
79
|
end
|
77
80
|
bootstrap.config[:tags] = bootstrap_tags
|
78
81
|
bootstrap.config[:distro] = bootstrap_distro
|
@@ -81,7 +84,7 @@ class Chef
|
|
81
84
|
|
82
85
|
def ec2_connection
|
83
86
|
@ec2_connection ||= Fog::Compute.new(
|
84
|
-
:provider =>
|
87
|
+
:provider => "AWS",
|
85
88
|
:aws_access_key_id => config_val(:aws_access_key_id),
|
86
89
|
:aws_secret_access_key => config_val(:aws_secret_access_key),
|
87
90
|
:region => config_val(:region)
|
@@ -91,8 +94,8 @@ class Chef
|
|
91
94
|
def server_dns_name
|
92
95
|
server = ec2_connection.servers.find do |s|
|
93
96
|
s.state == "running" &&
|
94
|
-
s.tags[
|
95
|
-
s.tags[
|
97
|
+
s.tags["Name"] == config_val(:chef_node_name) &&
|
98
|
+
s.tags["Role"] == "chef_server"
|
96
99
|
end
|
97
100
|
|
98
101
|
server && server.dns_name
|
@@ -101,6 +104,8 @@ class Chef
|
|
101
104
|
private
|
102
105
|
|
103
106
|
def validate!
|
107
|
+
super
|
108
|
+
|
104
109
|
if config[:chef_node_name].nil?
|
105
110
|
ui.error "You did not provide a valid --node-name value."
|
106
111
|
exit 1
|
@@ -111,8 +116,16 @@ class Chef
|
|
111
116
|
end
|
112
117
|
end
|
113
118
|
|
119
|
+
def setup_environment
|
120
|
+
ENV["WEBUI_PASSWORD"] = config_val(:webui_password)
|
121
|
+
ENV["AMQP_PASSWORD"] = config_val(:amqp_password)
|
122
|
+
ENV["NO_TEST"] = "1" if config[:no_test]
|
123
|
+
end
|
124
|
+
|
114
125
|
def config_security_group(name = nil)
|
115
|
-
|
126
|
+
ids = config[:security_group_ids]
|
127
|
+
|
128
|
+
if ids.nil? || ids.empty?
|
116
129
|
name = config_val(:security_groups).first if name.nil?
|
117
130
|
::Knife::Server::Ec2SecurityGroup.new(ec2_connection, ui).
|
118
131
|
configure_chef_server_group(name, :description => "#{name} group")
|
@@ -122,8 +135,8 @@ class Chef
|
|
122
135
|
end
|
123
136
|
|
124
137
|
def bootstrap_tags
|
125
|
-
Hash[Array(config_val(:tags)).map { |t| t.split(
|
126
|
-
merge(
|
138
|
+
Hash[Array(config_val(:tags)).map { |t| t.split("=") }].
|
139
|
+
merge("Role" => "chef_server").map { |k, v| "#{k}=#{v}" }
|
127
140
|
end
|
128
141
|
|
129
142
|
def ssh_connection
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
1
2
|
#
|
2
3
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
3
4
|
# Copyright:: Copyright (c) 2013 Fletcher Nichol
|
@@ -16,10 +17,11 @@
|
|
16
17
|
# limitations under the License.
|
17
18
|
#
|
18
19
|
|
19
|
-
require
|
20
|
+
require "chef/knife/server_bootstrap_base"
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Knife
|
24
|
+
# Provisions a Linode instance and sets up an Open Source Chef Server.
|
23
25
|
class ServerBootstrapLinode < Knife
|
24
26
|
|
25
27
|
banner "knife server bootstrap linode (options)"
|
@@ -27,17 +29,17 @@ class Chef
|
|
27
29
|
include Knife::ServerBootstrapBase
|
28
30
|
|
29
31
|
deps do
|
30
|
-
require
|
31
|
-
require
|
32
|
+
require "knife/server/ssh"
|
33
|
+
require "knife/server/credentials"
|
32
34
|
|
33
35
|
begin
|
34
|
-
require
|
35
|
-
require
|
36
|
+
require "chef/knife/linode_server_create"
|
37
|
+
require "fog"
|
36
38
|
Chef::Knife::LinodeServerCreate.load_deps
|
37
39
|
|
38
|
-
current_options =
|
40
|
+
current_options = options
|
39
41
|
self.options = Chef::Knife::LinodeServerCreate.options.dup
|
40
|
-
|
42
|
+
options.merge!(current_options)
|
41
43
|
rescue LoadError => ex
|
42
44
|
ui.error [
|
43
45
|
"Knife plugin knife-linode could not be loaded.",
|
@@ -50,7 +52,7 @@ class Chef
|
|
50
52
|
end
|
51
53
|
|
52
54
|
def run
|
53
|
-
|
55
|
+
super
|
54
56
|
linode_bootstrap.run
|
55
57
|
fetch_validation_key
|
56
58
|
create_root_client
|
@@ -58,12 +60,15 @@ class Chef
|
|
58
60
|
end
|
59
61
|
|
60
62
|
def linode_bootstrap
|
61
|
-
ENV[
|
62
|
-
ENV[
|
63
|
-
ENV[
|
63
|
+
ENV["WEBUI_PASSWORD"] = config_val(:webui_password)
|
64
|
+
ENV["AMQP_PASSWORD"] = config_val(:amqp_password)
|
65
|
+
ENV["NO_TEST"] = "1" if config[:no_test]
|
64
66
|
bootstrap = Chef::Knife::LinodeServerCreate.new
|
65
67
|
Chef::Knife::LinodeServerCreate.options.keys.each do |attr|
|
66
|
-
|
68
|
+
val = config_val(attr)
|
69
|
+
next if val.nil?
|
70
|
+
|
71
|
+
bootstrap.config[attr] = val
|
67
72
|
end
|
68
73
|
bootstrap.config[:distro] = bootstrap_distro
|
69
74
|
bootstrap
|
@@ -71,7 +76,7 @@ class Chef
|
|
71
76
|
|
72
77
|
def linode_connection
|
73
78
|
@linode_connection ||= Fog::Compute.new(
|
74
|
-
:provider =>
|
79
|
+
:provider => "Linode",
|
75
80
|
:linode_api_key => config_val(:linode_api_key)
|
76
81
|
)
|
77
82
|
end
|
@@ -87,6 +92,8 @@ class Chef
|
|
87
92
|
private
|
88
93
|
|
89
94
|
def validate!
|
95
|
+
super
|
96
|
+
|
90
97
|
if config[:chef_node_name].nil?
|
91
98
|
ui.error "You did not provide a valid --node-name value."
|
92
99
|
exit 1
|