conjur-cli 4.25.2 → 4.26.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/README.md +6 -0
- data/Rakefile +1 -33
- data/bin/{_conjur_completions → _conjur} +5 -26
- data/lib/conjur/command.rb +7 -4
- data/lib/conjur/command/audit.rb +10 -0
- data/lib/conjur/command/env.rb +1 -0
- data/lib/conjur/command/groups.rb +14 -15
- data/lib/conjur/command/hosts.rb +9 -9
- data/lib/conjur/command/init.rb +2 -0
- data/lib/conjur/command/layers.rb +22 -22
- data/lib/conjur/command/plugin.rb +6 -6
- data/lib/conjur/command/policy.rb +2 -2
- data/lib/conjur/command/pubkeys.rb +8 -8
- data/lib/conjur/command/resources.rb +30 -30
- data/lib/conjur/command/roles.rb +14 -14
- data/lib/conjur/command/rspec/audit_helpers.rb +0 -1
- data/lib/conjur/command/script.rb +2 -2
- data/lib/conjur/command/shellinit.rb +36 -0
- data/lib/conjur/command/users.rb +8 -8
- data/lib/conjur/command/variables.rb +12 -12
- data/lib/conjur/complete.rb +263 -0
- data/lib/conjur/version.rb +1 -1
- data/spec/command/audit_spec.rb +19 -0
- data/spec/complete_spec.rb +265 -0
- data/spec/spec_helper.rb +1 -0
- metadata +8 -6
- data/bin/_conjur_completions.yaml +0 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54ffbd129d6c3a3fc980ff0d44ad733b1eb384b6
|
4
|
+
data.tar.gz: 44d584a5a9a9e8aecff993113a31462fb7903392
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65c39293a9f24b0dc0ae51c13bf7921c30c99e74ed4f45a158f5f08c45dcc78eae530379bbcf264014150ab4a9e5d23bfa494f26f2e6a2b29bcb81732ddc10e9
|
7
|
+
data.tar.gz: c4f362e466e4fd8b3b0bd75e79a8e888849b8e51f3df8c29a92389d1f37c2ca14559877a95693a1c9a983d334ee6b0dcfd879167bc9cb83e84429e18ef3b16c6
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -16,36 +16,4 @@ task :jenkins => ['ci:setup:rspec', :spec, 'ci:setup:cucumber_report_cleanup'] d
|
|
16
16
|
File.write('build_number', ENV['BUILD_NUMBER']) if ENV['BUILD_NUMBER']
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
task :completions do
|
21
|
-
# having 'lib' in the load path, which happens to be the case when running rake,
|
22
|
-
# messes up GLIs commands_from
|
23
|
-
$:.delete('lib')
|
24
|
-
require 'conjur/cli'
|
25
|
-
require 'yaml'
|
26
|
-
|
27
|
-
Conjur::CLI.init!
|
28
|
-
def ignore? name
|
29
|
-
name = name.to_s
|
30
|
-
# Ignore GLIs internal commands and one of our deprecated ones
|
31
|
-
name.start_with?('_') or name.include?(':')
|
32
|
-
end
|
33
|
-
|
34
|
-
def visit cmd
|
35
|
-
child = {}
|
36
|
-
cmd.commands.each do |name, ccmd|
|
37
|
-
next if ignore?(name)
|
38
|
-
child[name] = visit(ccmd)
|
39
|
-
child[name] = true if child[name].empty?
|
40
|
-
end
|
41
|
-
child
|
42
|
-
end
|
43
|
-
|
44
|
-
commands = visit Conjur::CLI
|
45
|
-
|
46
|
-
File.open("#{File.dirname(__FILE__)}/bin/_conjur_completions.yaml", "w") do |io|
|
47
|
-
YAML.dump(commands, io)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
task default: [:completions, :spec, :features]
|
19
|
+
task default: [:spec, :features]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2015 Conjur Inc
|
4
4
|
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
6
|
# this software and associated documentation files (the "Software"), to deal in
|
@@ -20,29 +20,8 @@
|
|
20
20
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
#
|
22
22
|
|
23
|
-
|
24
|
-
#
|
25
|
-
# _conjur()
|
26
|
-
# {
|
27
|
-
# COMPREPLY=($(_conjur_completions $COMP_CWORD ${COMP_WORDS[@]}))
|
28
|
-
# }
|
29
|
-
# complete -F _conjur conjur
|
30
|
-
|
31
|
-
require 'yaml'
|
32
|
-
completions = File.open("#{File.dirname(__FILE__)}/_conjur_completions.yaml"){ |_| YAML.load(_) }
|
33
|
-
# ARGV[0] is the index into ARGV[1...] of the current word
|
34
|
-
index = ARGV[0].to_i - 1
|
35
|
-
words = ARGV[2..-1]
|
36
|
-
parents = words[0...index]
|
37
|
-
word = words[index] || ""
|
38
|
-
|
39
|
-
current = completions
|
40
|
-
previous = current
|
41
|
-
until parents.empty? or current.nil? or not current.kind_of?(Hash) # make sure to stop if we hit a 'true' entry
|
42
|
-
previous = current
|
43
|
-
current = current[parents.shift.to_sym]
|
44
|
-
end
|
23
|
+
require 'conjur/complete'
|
45
24
|
|
46
|
-
|
47
|
-
|
48
|
-
|
25
|
+
line = ENV['COMP_LINE']
|
26
|
+
point = ENV['COMP_POINT'].to_i
|
27
|
+
puts Conjur::CLI::Complete.new(line, point).completions
|
data/lib/conjur/command.rb
CHANGED
@@ -62,11 +62,13 @@ module Conjur
|
|
62
62
|
|
63
63
|
def acting_as_option command
|
64
64
|
return if command.flags.member?(:"as-group") # avoid duplicate flags
|
65
|
-
command.
|
66
|
-
command.
|
65
|
+
command.desc 'Perform all actions as the specified Group'
|
66
|
+
command.arg_name 'GROUP'
|
67
|
+
command.flag [:'as-group']
|
67
68
|
|
68
|
-
command.
|
69
|
-
command.
|
69
|
+
command.desc 'Perform all actions as the specified Role'
|
70
|
+
command.arg_name 'ROLE'
|
71
|
+
command.flag [:'as-role']
|
70
72
|
end
|
71
73
|
|
72
74
|
def interactive_option command
|
@@ -111,6 +113,7 @@ module Conjur
|
|
111
113
|
def command_options_for_list(c)
|
112
114
|
return if c.flags.member?(:role) # avoid duplicate flags
|
113
115
|
c.desc "Role to act as. By default, the current logged-in role is used."
|
116
|
+
c.arg_name 'ROLE'
|
114
117
|
c.flag [:role]
|
115
118
|
|
116
119
|
c.desc "Full-text search on resource id and annotation values"
|
data/lib/conjur/command/audit.rb
CHANGED
@@ -24,12 +24,22 @@ class Conjur::Command
|
|
24
24
|
"reported #{statement}"+ message_part
|
25
25
|
}
|
26
26
|
}
|
27
|
+
|
28
|
+
def ssh_sudo_message(e)
|
29
|
+
s = "#{e[:system_user]}"
|
30
|
+
s << " " << (e[:allowed] ? "ran" : "attempted to run")
|
31
|
+
s << " '" << e[:command] << "' as " << e[:target_user]
|
32
|
+
s
|
33
|
+
end
|
27
34
|
|
28
35
|
def short_event_format e
|
29
36
|
e.symbolize_keys!
|
30
37
|
s = "[#{Time.parse(e[:timestamp])}]"
|
31
38
|
s << " #{e[:user]}"
|
32
39
|
s << " (as #{e[:acting_as]})" if e[:acting_as] != e[:user]
|
40
|
+
if e[:facility] == 'ssh' && e[:action] == 'sudo'
|
41
|
+
e[:audit_message] = ssh_sudo_message(e)
|
42
|
+
end
|
33
43
|
formatter = SHORT_FORMATS["#{e[:kind]}:#{e[:action]}"] || SHORT_FORMATS[e[:kind]]
|
34
44
|
if formatter
|
35
45
|
s << " " << formatter.call(e)
|
data/lib/conjur/command/env.rb
CHANGED
@@ -30,7 +30,6 @@ class Conjur::Command::Groups < Conjur::Command
|
|
30
30
|
desc "Manage groups"
|
31
31
|
command :group do |group|
|
32
32
|
group.desc "Create a new group"
|
33
|
-
group.arg_name "id"
|
34
33
|
group.command :create do |c|
|
35
34
|
c.desc "GID number to be associated with the group (optional)"
|
36
35
|
c.flag [:gidnumber]
|
@@ -79,21 +78,21 @@ class Conjur::Command::Groups < Conjur::Command
|
|
79
78
|
end
|
80
79
|
|
81
80
|
group.desc "Show a group"
|
82
|
-
group.arg_name "
|
81
|
+
group.arg_name "GROUP"
|
83
82
|
group.command :show do |c|
|
84
83
|
c.action do |global_options,options,args|
|
85
|
-
id = require_arg(args, '
|
84
|
+
id = require_arg(args, 'GROUP')
|
86
85
|
display(api.group(id), options)
|
87
86
|
end
|
88
87
|
end
|
89
88
|
|
90
89
|
group.desc "Update group's attributes (eg. gidnumber)"
|
91
|
-
group.arg_name "
|
90
|
+
group.arg_name "GROUP"
|
92
91
|
group.command :update do |c|
|
93
92
|
c.desc "GID number to be associated with the group"
|
94
93
|
c.flag [:gidnumber]
|
95
94
|
c.action do |global_options, options, args|
|
96
|
-
id = require_arg(args, '
|
95
|
+
id = require_arg(args, 'GROUP')
|
97
96
|
|
98
97
|
options[:gidnumber] = Integer(options[:gidnumber])
|
99
98
|
api.group(id).update(options)
|
@@ -112,12 +111,12 @@ class Conjur::Command::Groups < Conjur::Command
|
|
112
111
|
end
|
113
112
|
|
114
113
|
group.desc "Decommission a group"
|
115
|
-
group.arg_name "
|
114
|
+
group.arg_name "GROUP"
|
116
115
|
group.command :retire do |c|
|
117
116
|
retire_options c
|
118
117
|
|
119
118
|
c.action do |global_options,options,args|
|
120
|
-
id = require_arg(args, '
|
119
|
+
id = require_arg(args, 'GROUP')
|
121
120
|
|
122
121
|
group = api.group(id)
|
123
122
|
|
@@ -135,18 +134,18 @@ class Conjur::Command::Groups < Conjur::Command
|
|
135
134
|
group.command :members do |members|
|
136
135
|
|
137
136
|
members.desc "Lists all direct members of the group. The membership list is not recursively expanded."
|
138
|
-
members.arg_name "
|
137
|
+
members.arg_name "GROUP"
|
139
138
|
members.command :list do |c|
|
140
139
|
c.desc "Verbose output"
|
141
140
|
c.switch [:V,:verbose]
|
142
141
|
c.action do |global_options,options,args|
|
143
|
-
group = require_arg(args, '
|
142
|
+
group = require_arg(args, 'GROUP')
|
144
143
|
display_members api.group(group).role.members, options
|
145
144
|
end
|
146
145
|
end
|
147
146
|
|
148
147
|
members.desc "Add a new group member"
|
149
|
-
members.arg_name "
|
148
|
+
members.arg_name "GROUP USER"
|
150
149
|
members.command :add do |c|
|
151
150
|
c.desc "Also grant the admin option"
|
152
151
|
c.switch [:a, :admin]
|
@@ -158,8 +157,8 @@ class Conjur::Command::Groups < Conjur::Command
|
|
158
157
|
c.switch [:r, :'revoke-admin']
|
159
158
|
|
160
159
|
c.action do |global_options,options,args|
|
161
|
-
group = require_arg(args, '
|
162
|
-
member = require_arg(args, '
|
160
|
+
group = require_arg(args, 'GROUP')
|
161
|
+
member = require_arg(args, 'USER')
|
163
162
|
member = assume_user_kind(member)
|
164
163
|
|
165
164
|
group = api.group(group)
|
@@ -179,11 +178,11 @@ class Conjur::Command::Groups < Conjur::Command
|
|
179
178
|
end
|
180
179
|
|
181
180
|
members.desc "Remove a group member"
|
182
|
-
members.arg_name "
|
181
|
+
members.arg_name "GROUP USER"
|
183
182
|
members.command :remove do |c|
|
184
183
|
c.action do |global_options,options,args|
|
185
|
-
group = require_arg(args, '
|
186
|
-
member = require_arg(args, '
|
184
|
+
group = require_arg(args, 'GROUP')
|
185
|
+
member = require_arg(args, 'USER')
|
187
186
|
member = assume_user_kind(member)
|
188
187
|
|
189
188
|
api.group(group).remove_member member
|
data/lib/conjur/command/hosts.rb
CHANGED
@@ -27,7 +27,7 @@ class Conjur::Command::Hosts < Conjur::Command
|
|
27
27
|
desc "Manage hosts"
|
28
28
|
command :host do |hosts|
|
29
29
|
hosts.desc "Create a new host"
|
30
|
-
hosts.arg_name "
|
30
|
+
hosts.arg_name "NAME"
|
31
31
|
hosts.command :create do |c|
|
32
32
|
c.arg_name "password"
|
33
33
|
c.flag [:p,:password]
|
@@ -47,21 +47,21 @@ class Conjur::Command::Hosts < Conjur::Command
|
|
47
47
|
end
|
48
48
|
|
49
49
|
hosts.desc "Show a host"
|
50
|
-
hosts.arg_name "
|
50
|
+
hosts.arg_name "HOST"
|
51
51
|
hosts.command :show do |c|
|
52
52
|
c.action do |global_options,options,args|
|
53
|
-
id = require_arg(args, '
|
53
|
+
id = require_arg(args, 'HOST')
|
54
54
|
display(api.host(id), options)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
hosts.desc "Decommission a host"
|
59
|
-
hosts.arg_name "
|
59
|
+
hosts.arg_name "HOST"
|
60
60
|
hosts.command :retire do |c|
|
61
61
|
retire_options c
|
62
62
|
|
63
63
|
c.action do |global_options,options,args|
|
64
|
-
id = require_arg(args, '
|
64
|
+
id = require_arg(args, 'HOST')
|
65
65
|
|
66
66
|
host = api.host(id)
|
67
67
|
|
@@ -89,11 +89,11 @@ class Conjur::Command::Hosts < Conjur::Command
|
|
89
89
|
end
|
90
90
|
|
91
91
|
hosts.desc "[Deprecated] Enroll a new host into conjur"
|
92
|
-
hosts.arg_name "
|
92
|
+
hosts.arg_name "HOST"
|
93
93
|
hosts.command :enroll do |c|
|
94
94
|
hide_docs(c)
|
95
95
|
c.action do |global_options, options, args|
|
96
|
-
id = require_arg(args, '
|
96
|
+
id = require_arg(args, 'HOST')
|
97
97
|
enrollment_url = api.host(id).enrollment_url
|
98
98
|
puts enrollment_url
|
99
99
|
$stderr.puts "On the target host, please execute the following command:"
|
@@ -102,10 +102,10 @@ class Conjur::Command::Hosts < Conjur::Command
|
|
102
102
|
end
|
103
103
|
|
104
104
|
hosts.desc "List the layers to which the host belongs"
|
105
|
-
hosts.arg_name "
|
105
|
+
hosts.arg_name "HOST"
|
106
106
|
hosts.command :layers do |c|
|
107
107
|
c.action do |global_options, options, args|
|
108
|
-
id = require_arg(args, '
|
108
|
+
id = require_arg(args, 'HOST')
|
109
109
|
host = api.host(id)
|
110
110
|
display host_layer_roles(host).map(&:identifier), options
|
111
111
|
end
|
data/lib/conjur/command/init.rb
CHANGED
@@ -39,6 +39,7 @@ class Conjur::Command::Init < Conjur::Command
|
|
39
39
|
|
40
40
|
Conjur::CLI.command :init do |c|
|
41
41
|
c.desc "Hostname of the Conjur endpoint (required for virtual appliance)"
|
42
|
+
c.arg_name 'HOSTNAME'
|
42
43
|
c.flag ["h", "hostname"]
|
43
44
|
|
44
45
|
c.desc "Conjur organization account name (not required for appliance)"
|
@@ -48,6 +49,7 @@ class Conjur::Command::Init < Conjur::Command
|
|
48
49
|
c.flag ["c", "certificate"]
|
49
50
|
|
50
51
|
c.desc "File to write the configuration to"
|
52
|
+
c.arg_name 'FILE'
|
51
53
|
c.flag ["f", "file"]
|
52
54
|
|
53
55
|
c.desc "Force overwrite of existing files"
|
@@ -6,7 +6,7 @@ class Conjur::Command::Layers < Conjur::Command
|
|
6
6
|
# Form an account:kind:hostid from the host argument
|
7
7
|
# Or interpret a fully-qualified role id
|
8
8
|
def self.require_hostid_arg(args)
|
9
|
-
hostid = require_arg(args, '
|
9
|
+
hostid = require_arg(args, 'HOST')
|
10
10
|
unless hostid.index(':')
|
11
11
|
hostid = [ Conjur::Core::API.conjur_account, 'host', hostid ].join(':')
|
12
12
|
end
|
@@ -25,9 +25,9 @@ class Conjur::Command::Layers < Conjur::Command
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.parse_layer_permission_args(global_options, options, args)
|
28
|
-
id = require_arg(args, "
|
29
|
-
role = require_arg(args, "
|
30
|
-
privilege = require_arg(args, "
|
28
|
+
id = require_arg(args, "LAYER")
|
29
|
+
role = require_arg(args, "ROLE")
|
30
|
+
privilege = require_arg(args, "PRIVILEGE")
|
31
31
|
role_name = interpret_layer_privilege privilege
|
32
32
|
[ id, role_name, role ]
|
33
33
|
end
|
@@ -36,12 +36,12 @@ class Conjur::Command::Layers < Conjur::Command
|
|
36
36
|
command :layer do |layer|
|
37
37
|
|
38
38
|
layer.desc "Create a new layer"
|
39
|
-
layer.arg_name "
|
39
|
+
layer.arg_name "LAYER"
|
40
40
|
layer.command :create do |c|
|
41
41
|
acting_as_option(c)
|
42
42
|
|
43
43
|
c.action do |global_options,options,args|
|
44
|
-
id = require_arg(args, '
|
44
|
+
id = require_arg(args, 'LAYER')
|
45
45
|
|
46
46
|
layer = api.create_layer(id, options)
|
47
47
|
display(layer, options)
|
@@ -58,33 +58,33 @@ class Conjur::Command::Layers < Conjur::Command
|
|
58
58
|
end
|
59
59
|
|
60
60
|
layer.desc "Show a layer"
|
61
|
-
layer.arg_name "
|
61
|
+
layer.arg_name "LAYER"
|
62
62
|
layer.command :show do |c|
|
63
63
|
c.action do |global_options,options,args|
|
64
|
-
id = require_arg(args, '
|
64
|
+
id = require_arg(args, 'LAYER')
|
65
65
|
display(api.layer(id), options)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
layer.desc "Provision a layer by creating backing resources in an IaaS / PaaS system"
|
70
|
-
layer.arg_name "
|
70
|
+
layer.arg_name "LAYER"
|
71
71
|
layer.command :provision do |c|
|
72
72
|
hide_docs(c)
|
73
73
|
|
74
74
|
c.desc "Provisioner to use (aws)"
|
75
|
-
c.arg_name "
|
75
|
+
c.arg_name "PROVISIONER"
|
76
76
|
c.flag [ :provisioner ]
|
77
77
|
|
78
78
|
c.desc "Variable holding a credential used to connect to the provisioner"
|
79
|
-
c.arg_name "
|
79
|
+
c.arg_name "VARIABLE"
|
80
80
|
c.flag [ :credential ]
|
81
81
|
|
82
82
|
c.desc "AWS bucket to contain the bootstrap credentials (will be created if missing)"
|
83
|
-
c.arg_name "
|
83
|
+
c.arg_name "BUCKET"
|
84
84
|
c.flag [ :bucket ]
|
85
85
|
|
86
86
|
c.action do |global_options, options, args|
|
87
|
-
id = require_arg(args, '
|
87
|
+
id = require_arg(args, 'LAYER')
|
88
88
|
provisioner = options[:provisioner] or exit_now!("Missing argument: provisioner")
|
89
89
|
credential = options[:credential] or exit_now!("Missing argument: credential")
|
90
90
|
bucket = options[:bucket] or exit_now!("Missing argument: bucket")
|
@@ -110,7 +110,7 @@ class Conjur::Command::Layers < Conjur::Command
|
|
110
110
|
hosts.long_desc <<-DESC
|
111
111
|
Privilege may be : execute, update
|
112
112
|
DESC
|
113
|
-
hosts.arg_name "
|
113
|
+
hosts.arg_name "LAYER ROLE PRIVILEGE"
|
114
114
|
hosts.command :permit do |c|
|
115
115
|
c.action do |global_options,options,args|
|
116
116
|
id, role_name, role = parse_layer_permission_args(global_options, options, args)
|
@@ -120,7 +120,7 @@ Privilege may be : execute, update
|
|
120
120
|
end
|
121
121
|
|
122
122
|
hosts.desc "Remove a privilege on hosts in the layer"
|
123
|
-
hosts.arg_name "
|
123
|
+
hosts.arg_name "LAYER ROLE PRIVILEGE"
|
124
124
|
hosts.command :deny do |c|
|
125
125
|
c.action do |global_options,options,args|
|
126
126
|
id, role_name, role = parse_layer_permission_args(global_options, options, args)
|
@@ -130,11 +130,11 @@ Privilege may be : execute, update
|
|
130
130
|
end
|
131
131
|
|
132
132
|
hosts.desc "List roles that have permission on the hosts"
|
133
|
-
hosts.arg_name "
|
133
|
+
hosts.arg_name "LAYER PRIVILEGE"
|
134
134
|
hosts.command :permitted_roles do |c|
|
135
135
|
c.action do |global_options,options,args|
|
136
|
-
id = require_arg(args,
|
137
|
-
role_name = interpret_layer_privilege require_arg(args,
|
136
|
+
id = require_arg(args, 'LAYER')
|
137
|
+
role_name = interpret_layer_privilege require_arg(args, 'PRIVILEGE')
|
138
138
|
|
139
139
|
members = api.layer(id).hosts_members(role_name).map(&:member).select do |m|
|
140
140
|
m.kind != "@"
|
@@ -144,10 +144,10 @@ Privilege may be : execute, update
|
|
144
144
|
end
|
145
145
|
|
146
146
|
hosts.desc "Add a host to an layer"
|
147
|
-
hosts.arg_name "
|
147
|
+
hosts.arg_name "LAYER HOST"
|
148
148
|
hosts.command :add do |c|
|
149
149
|
c.action do |global_options, options, args|
|
150
|
-
id = require_arg(args, '
|
150
|
+
id = require_arg(args, 'LAYER')
|
151
151
|
hostid = require_hostid_arg(args)
|
152
152
|
|
153
153
|
api.layer(id).add_host hostid
|
@@ -156,10 +156,10 @@ Privilege may be : execute, update
|
|
156
156
|
end
|
157
157
|
|
158
158
|
hosts.desc "Remove a host from an layer"
|
159
|
-
hosts.arg_name "
|
159
|
+
hosts.arg_name "LAYER HOST"
|
160
160
|
hosts.command :remove do |c|
|
161
161
|
c.action do |global_options, options, args|
|
162
|
-
id = require_arg(args, '
|
162
|
+
id = require_arg(args, 'LAYER')
|
163
163
|
hostid = require_hostid_arg(args)
|
164
164
|
|
165
165
|
api.layer(id).remove_host hostid
|