crowbar-client 2.3.0 → 2.4.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/lib/crowbar/client/app/backup.rb +87 -21
  4. data/lib/crowbar/client/app/base.rb +20 -0
  5. data/lib/crowbar/client/app/batch.rb +44 -31
  6. data/lib/crowbar/client/app/host_ip.rb +2 -0
  7. data/lib/crowbar/client/app/interface.rb +2 -0
  8. data/lib/crowbar/client/app/virtual_ip.rb +2 -0
  9. data/lib/crowbar/client/command/backup.rb +3 -0
  10. data/lib/crowbar/client/command/backup/delete.rb +2 -0
  11. data/lib/crowbar/client/command/backup/download.rb +21 -14
  12. data/lib/crowbar/client/command/backup/list.rb +6 -3
  13. data/lib/crowbar/client/command/backup/restore.rb +42 -0
  14. data/lib/crowbar/client/command/backup/upload.rb +13 -0
  15. data/lib/crowbar/client/command/base.rb +3 -0
  16. data/lib/crowbar/client/command/batch/build.rb +26 -0
  17. data/lib/crowbar/client/command/batch/export.rb +43 -0
  18. data/lib/crowbar/client/command/installer/start.rb +2 -0
  19. data/lib/crowbar/client/filter/hash.rb +1 -1
  20. data/lib/crowbar/client/request/backup.rb +3 -0
  21. data/lib/crowbar/client/request/backup/create.rb +1 -3
  22. data/lib/crowbar/client/request/backup/delete.rb +1 -1
  23. data/lib/crowbar/client/request/backup/download.rb +1 -1
  24. data/lib/crowbar/client/request/backup/restore.rb +38 -0
  25. data/lib/crowbar/client/request/backup/upload.rb +0 -2
  26. data/lib/crowbar/client/request/batch/build.rb +17 -2
  27. data/lib/crowbar/client/request/batch/export.rb +22 -2
  28. data/lib/crowbar/client/version.rb +1 -1
  29. data/spec/crowbar/client/command/backup/create_spec.rb +1 -3
  30. data/spec/crowbar/client/command/backup/delete_spec.rb +1 -2
  31. data/spec/crowbar/client/command/backup/download_spec.rb +1 -1
  32. data/spec/crowbar/client/command/backup/restore_spec.rb +40 -0
  33. data/spec/crowbar/client/command/backup/upload_spec.rb +4 -1
  34. data/spec/crowbar/client/command/batch/build_spec.rb +5 -1
  35. data/spec/crowbar/client/request/backup/create_spec.rb +2 -4
  36. data/spec/crowbar/client/request/backup/delete_spec.rb +2 -2
  37. data/spec/crowbar/client/request/backup/download_spec.rb +2 -2
  38. data/spec/crowbar/client/request/backup/list_spec.rb +2 -4
  39. data/spec/crowbar/client/request/backup/restore_spec.rb +52 -0
  40. data/spec/crowbar/client/request/batch/build_spec.rb +35 -44
  41. data/spec/crowbar/client/request/batch/export_spec.rb +33 -44
  42. data/spec/crowbar/client/request/proposal/create_spec.rb +2 -1
  43. data/spec/crowbar/client/request/proposal/edit_spec.rb +2 -1
  44. data/spec/fixtures/batch.yml +0 -0
  45. metadata +11 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 196e25c8ac9b8112656985164751b9a51b732178
4
- data.tar.gz: 3d281cb6d8561bc51f78d9aae02517b714761d0f
3
+ metadata.gz: ad1e74fd43f734f1de83365be861088e5fe578f3
4
+ data.tar.gz: 7227247e2f6d0650fbaaa3a4ee94e3560f16324b
5
5
  SHA512:
6
- metadata.gz: ba6e3e297bd4a9d22c6c737c040101af78dbf2b1c70b9ee70eddb377f72e844b3759e098dcbd646998ebababb04d9c6070d666048b95eb6bdcfa58387c99fefe
7
- data.tar.gz: 8572d1bb1472e8a57133bd94731205783011803fb5902ef8f0947591350f6197b2bd19fc1237defeec06c6a455d6352e58a2c4d9f2c85976a9b20424d0b8dfd6
6
+ metadata.gz: 48598a6ec995593fc838e7a5dfa08a476605445fb7fc0d2d6f643e1ab88b73d812b1c8e07ebc546305d72db39cdbfbeeabf2019f4c87ea38ed432b3c6079cf0d
7
+ data.tar.gz: 0deaf315129041b3fdd4209734324170476de4a6bb9b21324d6c525f957d781d7c37a2cbaa81d539e3555674b7f781e224d391ae41714343596b09e1e39bf34e
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.4.0](https://github.com/crowbar/crowbar-client/releases/tag/v2.4.0) - 2015-01-27
4
+
5
+ * BUGFIX
6
+ * Fixed backup commands by name (@tboerger)
7
+ * Fixed help output for nested commands (@tboerger)
8
+ * ENHANCEMENT
9
+ * Added subcommand to trigger a backup restore (@tboerger)
10
+ * Added subcommand for batch build and export (@tboerger)
11
+
3
12
  ## [2.3.0](https://github.com/crowbar/crowbar-client/releases/tag/v2.3.0) - 2015-01-15
4
13
 
5
14
  * BREAKING
@@ -22,9 +22,9 @@ module Crowbar
22
22
  "List existing backups"
23
23
 
24
24
  long_desc <<-LONGDESC
25
- `list` will print out a list of existing backups on the admin
26
- node. You can display the list in different output
27
- formats and you can filter the list by any search criteria.
25
+ `list` will print out a list of existing backups on the server.
26
+ You can display the list in different output formats and you
27
+ can filter the list by any search criteria.
28
28
 
29
29
  With --format <format> option you can choose an output format
30
30
  with the available options table, json or plain. You can also
@@ -73,34 +73,71 @@ module Crowbar
73
73
  catch_errors(e)
74
74
  end
75
75
 
76
+ desc "restore NAME",
77
+ "Restore from a backup"
78
+
79
+ long_desc <<-LONGDESC
80
+ `restore NAME` will trigger the restore process based on the
81
+ specified backup name. This command will override the proposals
82
+ of your server.
83
+
84
+ With --yes option you can force the restore without any further
85
+ question, this skips the otherwise required confirmation.
86
+ LONGDESC
87
+
88
+ method_option :yes,
89
+ type: :boolean,
90
+ default: false,
91
+ aliases: [],
92
+ desc: "Force the restore without any confirmation message"
93
+
94
+ def restore(name)
95
+ unless accepts_restore?
96
+ say "Canceled restore"
97
+ return
98
+ end
99
+
100
+ Command::Backup::Restore.new(
101
+ *command_params(
102
+ name: name
103
+ )
104
+ ).execute
105
+ rescue => e
106
+ catch_errors(e)
107
+ end
108
+
76
109
  desc "create",
77
110
  "Create a new backup"
78
111
 
79
112
  long_desc <<-LONGDESC
80
- `create NAME` will create a new backup on the Administration Server.
113
+ `create NAME` will trigger the creation of a new backup on the
114
+ server, to download the backup after processing you can use the
115
+ download command.
81
116
  LONGDESC
82
117
 
83
118
  def create(name)
84
119
  Command::Backup::Create.new(
85
120
  *command_params(
86
- backup: name
121
+ name: name
87
122
  )
88
123
  ).execute
89
124
  rescue => e
90
125
  catch_errors(e)
91
126
  end
92
127
 
93
- desc "download",
94
- "Download a backup"
128
+ desc "delete",
129
+ "Delete a backup"
95
130
 
96
131
  long_desc <<-LONGDESC
97
- `download ID` will download a backup from the Administration Server.
132
+ `delete NAME` will delete a backup from the server. Be careful
133
+ with that command, you are not able to restore this file after
134
+ deletion.
98
135
  LONGDESC
99
136
 
100
- def download(id)
101
- Command::Backup::Download.new(
137
+ def delete(name)
138
+ Command::Backup::Delete.new(
102
139
  *command_params(
103
- id: id
140
+ name: name
104
141
  )
105
142
  ).execute
106
143
  rescue => e
@@ -111,37 +148,66 @@ module Crowbar
111
148
  "Upload a backup"
112
149
 
113
150
  long_desc <<-LONGDESC
114
- `upload FILE` will upload a backup to the Administration Server.
151
+ `upload FILE` will upload a backup to the server. You can use
152
+ this backup later to trigger a restore.
115
153
  LONGDESC
116
154
 
117
155
  def upload(file)
118
156
  Command::Backup::Upload.new(
119
157
  *command_params(
120
- file: File.new(
121
- file
122
- )
158
+ file: file
123
159
  )
124
160
  ).execute
125
161
  rescue => e
126
162
  catch_errors(e)
127
163
  end
128
164
 
129
- desc "delete",
130
- "Delete a backup"
165
+ desc "download",
166
+ "Download a backup"
131
167
 
132
168
  long_desc <<-LONGDESC
133
- `delete ID` will delete a backup from the Administration Server.
169
+ `download NAME [FILE]` will download a backup from the server. If
170
+ you specify a `file` the download gets written to that file,
171
+ otherwise it gets saved to the current working directory with an
172
+ automatically generated filename. You can directly provide a path
173
+ to a file or just pipe the content to stdout. To pipe the content
174
+ to stdout you should just write a `-` instead of a specific
175
+ filename.
134
176
  LONGDESC
135
177
 
136
- def delete(id)
137
- Command::Backup::Delete.new(
178
+ def download(name, file = nil)
179
+ Command::Backup::Download.new(
138
180
  *command_params(
139
- id: id
181
+ name: name,
182
+ file: file
140
183
  )
141
184
  ).execute
142
185
  rescue => e
143
186
  catch_errors(e)
144
187
  end
188
+
189
+ no_commands do
190
+ def accepts_restore?
191
+ return true if options[:yes]
192
+
193
+ question = <<-QUESTION.strip_heredoc
194
+ Usage of this command is dangerous as it overwrites the
195
+ current state of the server and the proposals. Are you
196
+ sure you want to proceed?
197
+ QUESTION
198
+
199
+ answer = ask(
200
+ question,
201
+ :red,
202
+ limited_to: [
203
+ "yes",
204
+ "no"
205
+ ]
206
+ )
207
+
208
+ answer == "yes"
209
+ end
210
+ end
145
211
  end
146
212
  end
147
213
  end
@@ -80,6 +80,26 @@ module Crowbar
80
80
  end
81
81
  end
82
82
  end
83
+
84
+ class << self
85
+ def handle_argument_error(command, error, args, arity)
86
+ $stderr.puts("Usage: #{banner(command)}")
87
+ exit(2)
88
+ end
89
+
90
+ def banner(command, namespace = nil, subcommand = true)
91
+ addition = command.formatted_usage(
92
+ self,
93
+ false,
94
+ subcommand
95
+ )
96
+
97
+ [
98
+ basename,
99
+ addition
100
+ ].compact.join(" ")
101
+ end
102
+ end
83
103
  end
84
104
  end
85
105
  end
@@ -28,24 +28,29 @@ module Crowbar
28
28
  stdin you should just write a `-` instead of a specific
29
29
  filename.
30
30
 
31
- With --include <barclamp[.proposal]> option you can process
32
- only a specific part from the provided YAML file structure.
31
+ With --includes BARCLAMP[.PROPOSAL] option you can process
32
+ only a specific part from the provided YAML file structure,
33
+ the `default` proposal will be taken if you don't provide a
34
+ proposal name. This option allows multiple values, separated
35
+ by a `,` from each other.
33
36
 
34
- With --exclude <barclamp[.proposal]> option you exclude
37
+ With --excludes BARCLAMP[.PROPOSAL] option you exclude
35
38
  specific parts from the provided YAML file structure to be
36
- processed.
39
+ processed, the `default` proposal will be taken if you don't
40
+ provide a proposal name. This option allows multiple values,
41
+ separated by a `,` from each other.
37
42
  LONGDESC
38
43
 
39
- method_option :include,
40
- type: :string,
41
- default: nil,
42
- banner: "<barclamp[.proposal]>",
44
+ method_option :includes,
45
+ type: :array,
46
+ default: [],
47
+ banner: "BARCLAMP[.PROPOSAL]",
43
48
  desc: "Include a specific barclamp or proposal for processing"
44
49
 
45
- method_option :exclude,
46
- type: :string,
47
- default: nil,
48
- banner: "<barclamp[.proposal]>",
50
+ method_option :excludes,
51
+ type: :array,
52
+ default: [],
53
+ banner: "BARCLAMP[.PROPOSAL]",
49
54
  desc: "Exclude a specific barclamp or proposal for processing"
50
55
 
51
56
  def build(file)
@@ -58,37 +63,45 @@ module Crowbar
58
63
  catch_errors(e)
59
64
  end
60
65
 
61
- desc "export PROPOSAL [PROPOSAL]",
62
- "Export proposals to stdout"
66
+ desc "export FILE",
67
+ "Export proposals to file or stdout"
63
68
 
64
69
  long_desc <<-LONGDESC
65
- `export PROPOSAL [PROPOSAL]` will collect the informations
66
- for the provided proposals and print it out to stdout in a
67
- YAML format that can be used to build again.
70
+ `export FILE` will collect the informations of the proposals
71
+ in a YAML format. You can directly provide a path to a file or
72
+ just pipe the content into stdout. To pipe the content to
73
+ stdout you should just write a `-` instead of a specific
74
+ filename.
68
75
 
69
- With --include <barclamp[.proposal]> option you can export
70
- only a specific part from the existing proposals.
76
+ With --includes BARCLAMP[.PROPOSAL] option you can export
77
+ only a specific part from the existing proposals, the `default`
78
+ proposal will be taken if you don't provide a proposal name.
79
+ This option allows multiple values, separated by a `,` from
80
+ each other.
71
81
 
72
- With --exclude <barclamp[.proposal]> option you exclude
73
- specific parts from the existing proposals to be exported.
82
+ With --excludes BARCLAMP[.PROPOSAL] option you exclude specific
83
+ parts from the existing proposals to be exported, the `default`
84
+ proposal will be taken if you don't provide a proposal name.
85
+ This option allows multiple values, separated by a `,` from
86
+ each other.
74
87
  LONGDESC
75
88
 
76
- method_option :include,
77
- type: :string,
78
- default: nil,
79
- banner: "<barclamp[.proposal]>",
89
+ method_option :includes,
90
+ type: :array,
91
+ default: [],
92
+ banner: "BARCLAMP[.PROPOSAL]",
80
93
  desc: "Include a specific barclamp or proposal for export"
81
94
 
82
- method_option :exclude,
83
- type: :string,
84
- default: nil,
85
- banner: "<barclamp[.proposal]>",
95
+ method_option :excludes,
96
+ type: :array,
97
+ default: [],
98
+ banner: "BARCLAMP[.PROPOSAL]",
86
99
  desc: "Exclude a specific barclamp or proposal for export"
87
100
 
88
- def export(*proposals)
101
+ def export(file)
89
102
  Command::Batch::Export.new(
90
103
  *command_params(
91
- proposals: proposals
104
+ file: file
92
105
  )
93
106
  ).execute
94
107
  rescue => e
@@ -18,6 +18,8 @@ module Crowbar
18
18
  module Client
19
19
  module App
20
20
  class HostIP < Base
21
+ namespace "network hostip"
22
+
21
23
  desc "allocate PROPOSAL NODE NETWORK RANGE [SUGGESTION]",
22
24
  "Allocate a host IP address"
23
25
 
@@ -18,6 +18,8 @@ module Crowbar
18
18
  module Client
19
19
  module App
20
20
  class Interface < Base
21
+ namespace "network interface"
22
+
21
23
  desc "enable PROPOSAL NODE NETWORK",
22
24
  "Enable a network interface"
23
25
 
@@ -18,6 +18,8 @@ module Crowbar
18
18
  module Client
19
19
  module App
20
20
  class VirtualIP < Base
21
+ namespace "network virtualip"
22
+
21
23
  desc "allocate PROPOSAL SERVICE NETWORK RANGE [SUGGESTION]",
22
24
  "Allocate a virtual IP address"
23
25
 
@@ -30,6 +30,9 @@ module Crowbar
30
30
  autoload :List,
31
31
  File.expand_path("../backup/list", __FILE__)
32
32
 
33
+ autoload :Restore,
34
+ File.expand_path("../backup/restore", __FILE__)
35
+
33
36
  autoload :Upload,
34
37
  File.expand_path("../backup/upload", __FILE__)
35
38
  end
@@ -30,6 +30,8 @@ module Crowbar
30
30
  case request.code
31
31
  when 200
32
32
  say "Successfully deleted the backup"
33
+ when 404
34
+ err "Backup does not exist"
33
35
  else
34
36
  err request.parsed_response["error"]
35
37
  end
@@ -14,8 +14,6 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require "httparty"
18
-
19
17
  module Crowbar
20
18
  module Client
21
19
  module Command
@@ -32,12 +30,14 @@ module Crowbar
32
30
  case request.code
33
31
  when 200
34
32
  if write(request.body)
35
- say "Successfully downloaded backup to #{path}"
33
+ say "Successfully downloaded backup"
36
34
  else
37
- say "Failed to download backup to #{path}"
35
+ err "Failed to download backup"
38
36
  end
37
+ when 404
38
+ err "Backup does not exist"
39
39
  else
40
- err request.parsed_response["error"]
40
+ err request.body
41
41
  end
42
42
  end
43
43
  end
@@ -45,21 +45,28 @@ module Crowbar
45
45
  protected
46
46
 
47
47
  def write(body)
48
- path.open("wb") do |f|
49
- f.binmode
50
- f.write body
48
+ path.binmode
49
+ path.write body
51
50
 
52
- true
53
- end
51
+ true
54
52
  rescue
53
+ path.unlink if path.file?
55
54
  false
56
55
  end
57
56
 
58
57
  def path
59
- filename = Request::Backup::List.new.process do |p|
60
- p.parsed_response.select { |s| s["id"] == args.id.to_i }
61
- end.first["name"]
62
- Pathname.new("#{filename}.tar.gz")
58
+ @path ||=
59
+ case args.file
60
+ when "-"
61
+ stdout.to_io
62
+ when File
63
+ args.file
64
+ else
65
+ File.new(
66
+ args.file || "#{args.name}.tar.gz",
67
+ File::CREAT | File::TRUNC | File::RDWR
68
+ )
69
+ end
63
70
  end
64
71
  end
65
72
  end
@@ -55,18 +55,21 @@ module Crowbar
55
55
  protected
56
56
 
57
57
  def headings
58
- ["Id", "Name", "Created", "Size", "Version"]
58
+ ["Name", "Created", "Size", "Version"]
59
59
  end
60
60
 
61
61
  def content_from(request)
62
62
  request.parsed_response.map do |row|
63
63
  row.slice(
64
- "id",
65
64
  "name",
66
65
  "created_at",
67
66
  "size",
68
67
  "version"
69
- )
68
+ ).tap do |values|
69
+ values["size"] = number_to_human_size(
70
+ values["size"]
71
+ )
72
+ end
70
73
  end
71
74
  end
72
75
  end