hammer_cli 0.0.18 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -314
- data/bin/hammer +45 -6
- data/config/cli.modules.d/module_config_template.yml +4 -0
- data/config/cli_config.template.yml +9 -11
- data/doc/developer_docs.md +1 -0
- data/doc/i18n.md +85 -0
- data/doc/installation.md +321 -0
- data/lib/hammer_cli.rb +3 -0
- data/lib/hammer_cli/abstract.rb +15 -24
- data/lib/hammer_cli/apipie/command.rb +13 -7
- data/lib/hammer_cli/apipie/options.rb +14 -16
- data/lib/hammer_cli/apipie/read_command.rb +6 -1
- data/lib/hammer_cli/apipie/resource.rb +48 -58
- data/lib/hammer_cli/apipie/write_command.rb +5 -1
- data/lib/hammer_cli/completer.rb +77 -21
- data/lib/hammer_cli/connection.rb +44 -0
- data/lib/hammer_cli/exception_handler.rb +15 -4
- data/lib/hammer_cli/exceptions.rb +6 -0
- data/lib/hammer_cli/i18n.rb +95 -0
- data/lib/hammer_cli/logger.rb +3 -3
- data/lib/hammer_cli/main.rb +12 -11
- data/lib/hammer_cli/modules.rb +19 -6
- data/lib/hammer_cli/options/normalizers.rb +42 -7
- data/lib/hammer_cli/options/option_definition.rb +2 -2
- data/lib/hammer_cli/output.rb +1 -0
- data/lib/hammer_cli/output/adapter/abstract.rb +20 -0
- data/lib/hammer_cli/output/adapter/base.rb +49 -78
- data/lib/hammer_cli/output/adapter/csv.rb +5 -5
- data/lib/hammer_cli/output/adapter/table.rb +41 -10
- data/lib/hammer_cli/output/dsl.rb +1 -1
- data/lib/hammer_cli/output/field_filter.rb +21 -0
- data/lib/hammer_cli/output/fields.rb +44 -78
- data/lib/hammer_cli/output/formatters.rb +38 -0
- data/lib/hammer_cli/settings.rb +28 -6
- data/lib/hammer_cli/shell.rb +58 -57
- data/lib/hammer_cli/utils.rb +14 -0
- data/lib/hammer_cli/validator.rb +5 -5
- data/lib/hammer_cli/version.rb +1 -1
- data/locale/Makefile +64 -0
- data/locale/hammer-cli.pot +203 -0
- data/locale/zanata.xml +29 -0
- data/test/unit/apipie/command_test.rb +42 -25
- data/test/unit/apipie/read_command_test.rb +10 -7
- data/test/unit/apipie/write_command_test.rb +9 -8
- data/test/unit/completer_test.rb +206 -21
- data/test/unit/connection_test.rb +68 -0
- data/test/unit/fixtures/apipie/architectures.json +153 -0
- data/test/unit/fixtures/apipie/documented.json +79 -0
- data/test/unit/fixtures/json_input/invalid.json +12 -0
- data/test/unit/fixtures/json_input/valid.json +12 -0
- data/test/unit/history_test.rb +71 -0
- data/test/unit/main_test.rb +9 -0
- data/test/unit/modules_test.rb +22 -6
- data/test/unit/options/field_filter_test.rb +27 -0
- data/test/unit/options/normalizers_test.rb +53 -0
- data/test/unit/output/adapter/base_test.rb +162 -10
- data/test/unit/output/adapter/csv_test.rb +16 -3
- data/test/unit/output/adapter/table_test.rb +97 -13
- data/test/unit/output/dsl_test.rb +74 -6
- data/test/unit/output/fields_test.rb +93 -62
- data/test/unit/output/formatters_test.rb +47 -0
- data/test/unit/settings_test.rb +35 -4
- data/test/unit/utils_test.rb +45 -0
- metadata +85 -4
- data/test/unit/apipie/fake_api.rb +0 -101
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe HammerCLI::Connection do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
# clean up global settings
|
7
|
+
HammerCLI::Connection.drop_all
|
8
|
+
HammerCLI::Settings.load({:_params => {:interactive => false}})
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:connection) { HammerCLI::Connection }
|
12
|
+
|
13
|
+
class Connector < HammerCLI::AbstractConnector
|
14
|
+
|
15
|
+
attr_reader :url
|
16
|
+
|
17
|
+
def initialize(params)
|
18
|
+
@url = params[:url]
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return the conection" do
|
25
|
+
conn = connection.create(:test, {})
|
26
|
+
conn.must_be_kind_of HammerCLI::AbstractConnector
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should create the connection only once" do
|
30
|
+
conn1 = connection.create(:test, {})
|
31
|
+
conn2 = connection.create(:test, {})
|
32
|
+
conn1.must_equal conn2
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should test the connection" do
|
36
|
+
connection.exist?(:test).must_equal false
|
37
|
+
conn1 = connection.create(:test, {})
|
38
|
+
connection.exist?(:test).must_equal true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should get the connection" do
|
42
|
+
conn1 = connection.create(:test, {})
|
43
|
+
conn2 = connection.get(:test)
|
44
|
+
conn1.must_equal conn2
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
it "should be able to drop all" do
|
49
|
+
conn1 = connection.create(:test, {})
|
50
|
+
connection.drop_all
|
51
|
+
conn2 = connection.create(:test, {})
|
52
|
+
conn1.wont_equal conn2 # TODO
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should drop the connection" do
|
56
|
+
conn1 = connection.create(:test, {})
|
57
|
+
connection.drop(:test)
|
58
|
+
conn2 = connection.create(:test, {})
|
59
|
+
conn1.wont_equal conn2
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should accept custom connector" do
|
63
|
+
conn = connection.create(:test, {:url => 'URL'}, :connector => Connector)
|
64
|
+
conn.must_be_kind_of Connector
|
65
|
+
conn.url.must_equal 'URL'
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
{
|
2
|
+
"docs": {
|
3
|
+
"api_url": "/api",
|
4
|
+
"copyright": "",
|
5
|
+
"doc_url": "/apidoc/v2",
|
6
|
+
"info": "Another API description",
|
7
|
+
"name": "Foreman",
|
8
|
+
"resources": {
|
9
|
+
"architectures": {
|
10
|
+
"api_url": "/api",
|
11
|
+
"doc_url": "/apidoc/v2/architectures",
|
12
|
+
"formats": null,
|
13
|
+
"full_description": null,
|
14
|
+
"methods": [
|
15
|
+
{
|
16
|
+
"apis": [
|
17
|
+
{
|
18
|
+
"api_url": "/api/architectures",
|
19
|
+
"http_method": "GET",
|
20
|
+
"short_description": "List all architectures."
|
21
|
+
}
|
22
|
+
],
|
23
|
+
"doc_url": "/apidoc/v2/architectures/index",
|
24
|
+
"errors": [],
|
25
|
+
"examples": [
|
26
|
+
"GET /api/architectures\n200\n[\n {\n \"architecture\": {\n \"name\": \"s390\",\n \"id\": 381564594,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n },\n {\n \"architecture\": {\n \"name\": \"sparc\",\n \"id\": 331892513,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [\n 442321401\n ],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n },\n {\n \"architecture\": {\n \"name\": \"x86_64\",\n \"id\": 501905019,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [\n 331303656,\n 309172073,\n 1073012828\n ],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n }\n]"
|
27
|
+
],
|
28
|
+
"formats": null,
|
29
|
+
"full_description": "",
|
30
|
+
"name": "index",
|
31
|
+
"params": [
|
32
|
+
{
|
33
|
+
"allow_nil": false,
|
34
|
+
"description": "\n<p>filter results</p>\n",
|
35
|
+
"expected_type": "string",
|
36
|
+
"full_name": "search",
|
37
|
+
"name": "search",
|
38
|
+
"required": false,
|
39
|
+
"validator": "Must be String"
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"allow_nil": false,
|
43
|
+
"description": "\n<p>sort results</p>\n",
|
44
|
+
"expected_type": "string",
|
45
|
+
"full_name": "order",
|
46
|
+
"name": "order",
|
47
|
+
"required": false,
|
48
|
+
"validator": "Must be String"
|
49
|
+
},
|
50
|
+
{
|
51
|
+
"allow_nil": false,
|
52
|
+
"description": "\n<p>paginate results</p>\n",
|
53
|
+
"expected_type": "string",
|
54
|
+
"full_name": "page",
|
55
|
+
"name": "page",
|
56
|
+
"required": false,
|
57
|
+
"validator": "Must be String"
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"allow_nil": false,
|
61
|
+
"description": "\n<p>number of entries per request</p>\n",
|
62
|
+
"expected_type": "string",
|
63
|
+
"full_name": "per_page",
|
64
|
+
"name": "per_page",
|
65
|
+
"required": false,
|
66
|
+
"validator": "Must be String"
|
67
|
+
}
|
68
|
+
],
|
69
|
+
"see": []
|
70
|
+
},
|
71
|
+
{
|
72
|
+
"apis": [
|
73
|
+
{
|
74
|
+
"api_url": "/api/architectures/:id",
|
75
|
+
"http_method": "GET",
|
76
|
+
"short_description": "Show an architecture."
|
77
|
+
}
|
78
|
+
],
|
79
|
+
"doc_url": "/apidoc/v2/architectures/show",
|
80
|
+
"errors": [],
|
81
|
+
"examples": [
|
82
|
+
"GET /api/architectures/x86_64\n200\n{\n \"architecture\": {\n \"name\": \"x86_64\",\n \"id\": 501905019,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [\n 309172073,\n 1073012828,\n 331303656\n ],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n}"
|
83
|
+
],
|
84
|
+
"formats": null,
|
85
|
+
"full_description": "",
|
86
|
+
"name": "show",
|
87
|
+
"params": [
|
88
|
+
{
|
89
|
+
"allow_nil": false,
|
90
|
+
"description": "",
|
91
|
+
"expected_type": "string",
|
92
|
+
"full_name": "id",
|
93
|
+
"name": "id",
|
94
|
+
"required": true,
|
95
|
+
"validator": "Must be an identifier, string from 1 to 128 characters containing only alphanumeric characters, space, underscore(_), hypen(-) with no leading or trailing space."
|
96
|
+
}
|
97
|
+
],
|
98
|
+
"see": []
|
99
|
+
},
|
100
|
+
{
|
101
|
+
"apis": [
|
102
|
+
{
|
103
|
+
"api_url": "/api/architectures",
|
104
|
+
"http_method": "POST",
|
105
|
+
"short_description": "Create an architecture."
|
106
|
+
}
|
107
|
+
],
|
108
|
+
"doc_url": "/apidoc/v2/architectures/create",
|
109
|
+
"errors": [],
|
110
|
+
"examples": [
|
111
|
+
"POST /api/architectures\n{\n \"architecture\": {\n \"name\": \"i386\"\n }\n}\n200\n{\n \"architecture\": {\n \"name\": \"i386\",\n \"id\": 501905020,\n \"updated_at\": \"2012-12-18T15:24:43Z\",\n \"operatingsystem_ids\": [],\n \"created_at\": \"2012-12-18T15:24:43Z\"\n }\n}"
|
112
|
+
],
|
113
|
+
"formats": null,
|
114
|
+
"full_description": "",
|
115
|
+
"name": "create",
|
116
|
+
"params": [
|
117
|
+
{
|
118
|
+
"allow_nil": false,
|
119
|
+
"description": "",
|
120
|
+
"expected_type": "hash",
|
121
|
+
"full_name": "architecture",
|
122
|
+
"name": "architecture",
|
123
|
+
"params": [
|
124
|
+
{
|
125
|
+
"allow_nil": false,
|
126
|
+
"description": "",
|
127
|
+
"expected_type": "string",
|
128
|
+
"full_name": "architecture[name]",
|
129
|
+
"name": "name",
|
130
|
+
"required": true,
|
131
|
+
"validator": "Must be String"
|
132
|
+
},
|
133
|
+
{
|
134
|
+
"allow_nil": false,
|
135
|
+
"description": "\n<p>Operatingsystem ID\u2019s</p>\n",
|
136
|
+
"expected_type": "array",
|
137
|
+
"full_name": "architecture[operatingsystem_ids]",
|
138
|
+
"name": "operatingsystem_ids",
|
139
|
+
"required": false,
|
140
|
+
"validator": "Must be Array"
|
141
|
+
}
|
142
|
+
],
|
143
|
+
"required": true,
|
144
|
+
"validator": "Must be a Hash"
|
145
|
+
}
|
146
|
+
],
|
147
|
+
"see": []
|
148
|
+
}
|
149
|
+
]
|
150
|
+
}
|
151
|
+
}
|
152
|
+
}
|
153
|
+
}
|
@@ -0,0 +1,79 @@
|
|
1
|
+
{
|
2
|
+
"docs": {
|
3
|
+
"name": "Documented",
|
4
|
+
"api_url": "/api",
|
5
|
+
"version": "v2",
|
6
|
+
"short_description": null,
|
7
|
+
"full_description": null,
|
8
|
+
"doc_url": "/apidoc/v2/documented",
|
9
|
+
"resources": {
|
10
|
+
"documented": {
|
11
|
+
"methods": [
|
12
|
+
{
|
13
|
+
"name": "index",
|
14
|
+
"examples": [],
|
15
|
+
"errors": [],
|
16
|
+
"params": [
|
17
|
+
{
|
18
|
+
"allow_null": false,
|
19
|
+
"name": "se_arch_val-ue",
|
20
|
+
"full_name": "se_arch_val-ue_full_name",
|
21
|
+
"validator": "Must be String",
|
22
|
+
"description": "<p>filter results</p>",
|
23
|
+
"expected_type": "string",
|
24
|
+
"required": false
|
25
|
+
}
|
26
|
+
],
|
27
|
+
"full_description": ""
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"name": "create",
|
31
|
+
"examples": [],
|
32
|
+
"errors": [],
|
33
|
+
"params": [
|
34
|
+
{
|
35
|
+
"allow_null": false,
|
36
|
+
"name": "documented",
|
37
|
+
"full_name": "documented",
|
38
|
+
"validator": "Must be a Hash",
|
39
|
+
"description": "",
|
40
|
+
"expected_type": "hash",
|
41
|
+
"required": true,
|
42
|
+
"params": [
|
43
|
+
{
|
44
|
+
"name": "name",
|
45
|
+
"allow_null": false,
|
46
|
+
"full_name": "documented[name]",
|
47
|
+
"validator": "Must be String",
|
48
|
+
"expected_type": "string",
|
49
|
+
"description": "",
|
50
|
+
"required": false
|
51
|
+
},
|
52
|
+
{
|
53
|
+
"name": "provider",
|
54
|
+
"allow_null": false,
|
55
|
+
"full_name": "documented[provider]",
|
56
|
+
"validator": "Must be String",
|
57
|
+
"expected_type": "string",
|
58
|
+
"description": "<p>Providers include Libvirt, Ovirt, EC2, Vmware, Openstack, Rackspace</p>",
|
59
|
+
"required": false
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"name": "array_param",
|
63
|
+
"allow_null": false,
|
64
|
+
"full_name": "documented[array_param]",
|
65
|
+
"validator": "Must be Array",
|
66
|
+
"expected_type": "string",
|
67
|
+
"description": "",
|
68
|
+
"required": true
|
69
|
+
}
|
70
|
+
]
|
71
|
+
}
|
72
|
+
],
|
73
|
+
"full_description": ""
|
74
|
+
}
|
75
|
+
]
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
describe HammerCLI::ShellHistory do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
# Readline::HISOTRY does not implement #clear in Ruby 1.8
|
7
|
+
while not Readline::HISTORY.empty?
|
8
|
+
Readline::HISTORY.pop
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
let :history_file do
|
13
|
+
file = Tempfile.new('history')
|
14
|
+
file.puts "line 1"
|
15
|
+
file.puts "line 2"
|
16
|
+
file.close
|
17
|
+
file
|
18
|
+
end
|
19
|
+
|
20
|
+
let :new_file do
|
21
|
+
Tempfile.new('history')
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "loading old history" do
|
25
|
+
|
26
|
+
it "skips loading if the file does not exist" do
|
27
|
+
history = HammerCLI::ShellHistory.new(new_file.path)
|
28
|
+
|
29
|
+
Readline::HISTORY.to_a.must_equal []
|
30
|
+
end
|
31
|
+
|
32
|
+
it "preseeds readline's history" do
|
33
|
+
history = HammerCLI::ShellHistory.new(history_file.path)
|
34
|
+
|
35
|
+
Readline::HISTORY.to_a.must_equal ["line 1", "line 2"]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "saving history" do
|
40
|
+
it "creates history file if it does not exist" do
|
41
|
+
history = HammerCLI::ShellHistory.new(new_file.path)
|
42
|
+
history.push("some command ")
|
43
|
+
|
44
|
+
File.exist?(new_file.path).must_equal true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "appends history to the given file" do
|
48
|
+
history = HammerCLI::ShellHistory.new(new_file.path)
|
49
|
+
history.push("some command ")
|
50
|
+
history.push("another command ")
|
51
|
+
|
52
|
+
new_file.read.must_equal "some command\nanother command\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "appends to readline's history" do
|
56
|
+
history = HammerCLI::ShellHistory.new(history_file.path)
|
57
|
+
history.push("line 3")
|
58
|
+
|
59
|
+
Readline::HISTORY.to_a.must_equal ["line 1", "line 2", "line 3"]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "doesn't save exit command" do
|
63
|
+
history = HammerCLI::ShellHistory.new(history_file.path)
|
64
|
+
history.push("exit ")
|
65
|
+
|
66
|
+
Readline::HISTORY.to_a.must_equal ["line 1", "line 2"]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
data/test/unit/main_test.rb
CHANGED
data/test/unit/modules_test.rb
CHANGED
@@ -18,7 +18,8 @@ describe HammerCLI::Modules do
|
|
18
18
|
before :each do
|
19
19
|
HammerCLI::Settings.clear
|
20
20
|
HammerCLI::Settings.load({
|
21
|
-
:
|
21
|
+
:tom => { :enable_module => true },
|
22
|
+
:jerry => { :enable_module => true },
|
22
23
|
})
|
23
24
|
|
24
25
|
@log_output = Logging::Appenders['__test__']
|
@@ -27,13 +28,22 @@ describe HammerCLI::Modules do
|
|
27
28
|
|
28
29
|
describe "names" do
|
29
30
|
it "must return list of modules" do
|
30
|
-
HammerCLI::Modules.names.must_equal ["hammer_cli_tom", "hammer_cli_jerry"]
|
31
|
+
HammerCLI::Modules.names.sort.must_equal ["hammer_cli_tom", "hammer_cli_jerry"].sort
|
31
32
|
end
|
32
33
|
|
33
34
|
it "must return empty array by default" do
|
34
35
|
HammerCLI::Settings.clear
|
35
36
|
HammerCLI::Modules.names.must_equal []
|
36
37
|
end
|
38
|
+
|
39
|
+
it "must work with old modules config" do
|
40
|
+
HammerCLI::Settings.clear
|
41
|
+
HammerCLI::Settings.load({
|
42
|
+
:tom => {},
|
43
|
+
:modules => ['hammer_cli_tom', 'hammer_cli_jerry'],
|
44
|
+
})
|
45
|
+
HammerCLI::Modules.names.sort.must_equal ["hammer_cli_tom", "hammer_cli_jerry"].sort
|
46
|
+
end
|
37
47
|
end
|
38
48
|
|
39
49
|
describe "find by name" do
|
@@ -89,21 +99,27 @@ describe HammerCLI::Modules do
|
|
89
99
|
describe "module not found" do
|
90
100
|
before :each do
|
91
101
|
HammerCLI::Modules.stubs(:require_module).raises(LoadError)
|
92
|
-
@error_msg = "ERROR Modules :
|
102
|
+
@error_msg = "ERROR Modules : Error while loading module hammer_cli_tom"
|
93
103
|
end
|
94
104
|
|
95
105
|
it "must log an error if the load! fails" do
|
96
|
-
|
106
|
+
capture_io do
|
107
|
+
proc { HammerCLI::Modules.load!("hammer_cli_tom") }.must_raise LoadError
|
108
|
+
end
|
97
109
|
@log_output.readline.strip.must_equal @error_msg
|
98
110
|
end
|
99
111
|
|
100
112
|
it "must log an error if the load fails" do
|
101
|
-
|
113
|
+
capture_io do
|
114
|
+
HammerCLI::Modules.load("hammer_cli_tom")
|
115
|
+
end
|
102
116
|
@log_output.readline.strip.must_equal @error_msg
|
103
117
|
end
|
104
118
|
|
105
119
|
it "must return false when load fails" do
|
106
|
-
|
120
|
+
capture_io do
|
121
|
+
HammerCLI::Modules.load("hammer_cli_tom").must_equal false
|
122
|
+
end
|
107
123
|
end
|
108
124
|
end
|
109
125
|
|