knife-digital_ocean 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.md +112 -20
  4. data/Rakefile +6 -0
  5. data/knife-digital_ocean.gemspec +4 -0
  6. data/lib/chef/knife/digital_ocean_base.rb +15 -0
  7. data/lib/chef/knife/digital_ocean_domain_create.rb +9 -10
  8. data/lib/chef/knife/digital_ocean_domain_destroy.rb +5 -5
  9. data/lib/chef/knife/digital_ocean_domain_list.rb +1 -2
  10. data/lib/chef/knife/digital_ocean_domain_record_create.rb +18 -18
  11. data/lib/chef/knife/digital_ocean_domain_record_destroy.rb +9 -10
  12. data/lib/chef/knife/digital_ocean_domain_record_edit.rb +21 -21
  13. data/lib/chef/knife/digital_ocean_domain_record_list.rb +4 -5
  14. data/lib/chef/knife/digital_ocean_droplet_create.rb +4 -5
  15. data/lib/chef/knife/digital_ocean_droplet_destroy.rb +3 -6
  16. data/lib/chef/knife/digital_ocean_droplet_power.rb +66 -0
  17. data/lib/chef/knife/digital_ocean_droplet_powercycle.rb +48 -0
  18. data/lib/chef/knife/digital_ocean_droplet_reboot.rb +48 -0
  19. data/lib/chef/knife/digital_ocean_droplet_rebuild.rb +58 -0
  20. data/lib/chef/knife/digital_ocean_droplet_rename.rb +58 -0
  21. data/lib/chef/knife/digital_ocean_droplet_resize.rb +58 -0
  22. data/lib/chef/knife/digital_ocean_droplet_snapshot.rb +58 -0
  23. data/lib/chef/knife/digital_ocean_image_destroy.rb +42 -0
  24. data/lib/chef/knife/digital_ocean_image_list.rb +1 -1
  25. data/lib/chef/knife/digital_ocean_image_transfer.rb +66 -0
  26. data/lib/chef/knife/digital_ocean_region_list.rb +1 -1
  27. data/lib/chef/knife/digital_ocean_sshkey_create.rb +11 -11
  28. data/lib/chef/knife/digital_ocean_sshkey_destroy.rb +6 -6
  29. data/lib/chef/knife/digital_ocean_sshkey_list.rb +1 -1
  30. data/lib/knife-digital_ocean/version.rb +1 -1
  31. data/spec/fixtures/keys/id_rsa.pub +1 -0
  32. data/spec/fixtures/vcr_cassettes/accountinfo.yml +7 -9
  33. data/spec/fixtures/vcr_cassettes/domain_create.yml +65 -0
  34. data/spec/fixtures/vcr_cassettes/{domainlist.yml → domain_list.yml} +15 -12
  35. data/spec/fixtures/vcr_cassettes/domain_record_create.yml +65 -0
  36. data/spec/fixtures/vcr_cassettes/domain_record_list.yml +63 -0
  37. data/spec/fixtures/vcr_cassettes/droplet.yml +12 -17
  38. data/spec/fixtures/vcr_cassettes/droplet_power.yml +65 -0
  39. data/spec/fixtures/vcr_cassettes/droplet_powercycle.yml +127 -0
  40. data/spec/fixtures/vcr_cassettes/droplet_reboot.yml +127 -0
  41. data/spec/fixtures/vcr_cassettes/droplet_rebuild.yml +65 -0
  42. data/spec/fixtures/vcr_cassettes/droplet_rename.yml +127 -0
  43. data/spec/fixtures/vcr_cassettes/droplet_resize.yml +65 -0
  44. data/spec/fixtures/vcr_cassettes/droplet_snapshot.yml +1057 -0
  45. data/spec/fixtures/vcr_cassettes/image.yml +55 -59
  46. data/spec/fixtures/vcr_cassettes/public_images.yml +54 -59
  47. data/spec/fixtures/vcr_cassettes/region.yml +8 -10
  48. data/spec/fixtures/vcr_cassettes/sizes.yml +8 -10
  49. data/spec/fixtures/vcr_cassettes/sshkey.yml +8 -10
  50. data/spec/fixtures/vcr_cassettes/sshkey_create.yml +68 -0
  51. data/spec/lib/chef/knife/digital_ocean_account_info_spec.rb +4 -4
  52. data/spec/lib/chef/knife/digital_ocean_domain_create_spec.rb +35 -1
  53. data/spec/lib/chef/knife/digital_ocean_domain_list_spec.rb +8 -9
  54. data/spec/lib/chef/knife/digital_ocean_domain_record_create_spec.rb +37 -1
  55. data/spec/lib/chef/knife/digital_ocean_domain_record_list_spec.rb +34 -1
  56. data/spec/lib/chef/knife/digital_ocean_droplet_create_spec.rb +5 -1
  57. data/spec/lib/chef/knife/digital_ocean_droplet_list_spec.rb +4 -4
  58. data/spec/lib/chef/knife/digital_ocean_droplet_power_spec.rb +39 -0
  59. data/spec/lib/chef/knife/digital_ocean_droplet_powercycle_spec.rb +38 -0
  60. data/spec/lib/chef/knife/digital_ocean_droplet_reboot_spec.rb +38 -0
  61. data/spec/lib/chef/knife/digital_ocean_droplet_rebuild_spec.rb +39 -0
  62. data/spec/lib/chef/knife/digital_ocean_droplet_rename_spec.rb +39 -0
  63. data/spec/lib/chef/knife/digital_ocean_droplet_resize_spec.rb +39 -0
  64. data/spec/lib/chef/knife/digital_ocean_droplet_snapshot_spec.rb +39 -0
  65. data/spec/lib/chef/knife/digital_ocean_image_list_spec.rb +8 -10
  66. data/spec/lib/chef/knife/digital_ocean_region_list_spec.rb +4 -4
  67. data/spec/lib/chef/knife/digital_ocean_size_list_spec.rb +4 -4
  68. data/spec/lib/chef/knife/digital_ocean_sshkey_create_spec.rb +35 -1
  69. data/spec/lib/chef/knife/digital_ocean_sshkey_list_spec.rb +4 -4
  70. data/spec/spec_helper.rb +29 -2
  71. metadata +93 -6
  72. data/spec/lib/chef/knife/digital_ocean_domain_record_edit_spec.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20219152d6de37594c8b08a29627e41e6e52d245
4
- data.tar.gz: 18b24e2ef42827ca6052c5ee5e6828592bddd546
3
+ metadata.gz: 8650d8892865c192e800a905cc88407920c0f548
4
+ data.tar.gz: 4faf0a27ed93673948ee1ef1600f36ecdfa07700
5
5
  SHA512:
6
- metadata.gz: 513bc8bcac02b559db21dfb4624773ef1742ae09dd2ce3406415faec61fdf3d29565b49ca77954635b8d2aa4ef4dfc4a465ed83ca6cf5fdb05a84ba0a5cc2aa8
7
- data.tar.gz: 97b6fcae12fd43e3c06850a4bc418600e1c763cc9f00f94f3daf39d53e97e1ae6fa5a10f987fea3829584df6192133e6f27e814c4f85b89120ae18559afdcc93
6
+ metadata.gz: 8681c4b09a4c16db831e3b0712a72504dea777d74e0459c564c55246411a95f48944724b5efb43c4606d60dca706993d66859715a635ffb1394223e33c39343a
7
+ data.tar.gz: 1d9c70a286b5453b7c401d411ba53e6d2df7ca73060d0e4426efef377a39a4f53c05204623938816098d9d49c4641d8f9086b717fb9427c3e72391969bc93a9e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ 2.3.0 / 2014-11-18
2
+
3
+ * New subcommands
4
+ - knife digital_ocean droplet power
5
+ - knife digital_ocean droplet powercycle
6
+ - knife digital_ocean droplet reboot
7
+ - knife digital_ocean droplet snapshot
8
+ - knife digital_ocean droplet rename
9
+ - knife digital_ocean droplet rebuild
10
+ - knife digital_ocean droplet resize
11
+ - knife digital_ocean image transfer
12
+ * Removed hacky use of rescue
13
+ * Use sort_by in list commands, where it makes sense
14
+ * Add --bootstrap-version to examples, thanks to [@brandoncc ](https://github.com/brandoncc) [PR #54]
15
+ * Fix status check during droplet create
16
+
1
17
  ## 2.2.0 / 2014-11-14
2
18
 
3
19
  * Domain support, thanks to [@nozpheratu](https://github.com/nozpheratu) [PR #32]
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Knife::DigitalOcean
2
- ## A knife plugin to deal with the [DigitalOcean.com](https://www.digitalocean.com) Cloud services.
2
+ #### A knife plugin to deal with the [DigitalOcean.com](https://www.digitalocean.com) Cloud services.
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/knife-digital_ocean.png)](http://badge.fury.io/rb/knife-digital_ocean)
5
5
  [![Build Status](https://travis-ci.org/rmoriz/knife-digital_ocean.png)](https://travis-ci.org/rmoriz/knife-digital_ocean)
@@ -22,52 +22,79 @@ This knife plugin uses the [droplet_kit](https://github.com/digitalocean/droplet
22
22
 
23
23
  This plugin provides the following sub-commands:
24
24
 
25
- * knife digital_ocean droplet create (options)
26
- **Creates a virtual machine with or without bootstrapping chef**
25
+ * knife digital_ocean droplet create (options)
26
+ **Creates a virtual machine with or without bootstrapping chef**
27
27
 
28
- * knife digital_ocean droplet destroy (options)
28
+ * knife digital_ocean droplet destroy (options)
29
29
  **Destroys the virtual machine and its data**
30
30
 
31
- * knife digital_ocean droplet list (options)
31
+ * knife digital_ocean droplet list (options)
32
32
  **Lists currently running virtual machines**
33
33
 
34
- * knife digital_ocean image list (options)
34
+ * knife digital_ocean droplet power (options)
35
+ **Turn a droplet On/Off**
36
+
37
+ * knife digital_ocean droplet powercycle (options)
38
+ **Powercycle a Droplet**
39
+
40
+ * knife digital_ocean droplet reboot (options)
41
+ **Reboot a Droplet**
42
+
43
+ * knife digital_ocean droplet snapshot (options)
44
+ **Take a snapshot of a Droplet**
45
+
46
+ * knife digital_ocean droplet rename (options)
47
+ **Rename a Droplet**
48
+
49
+ * knife digital_ocean droplet rebuild (options)
50
+ **Rebuild a Droplet**
51
+
52
+ * knife digital_ocean droplet resize (options)
53
+ **Resize a Droplet**
54
+
55
+ * knife digital_ocean image destroy (options)
56
+ **Destroy your private images**
57
+
58
+ * knife digital_ocean image list (options)
35
59
  **Lists available images (snapshots, backups, OS-images)**
36
60
 
37
- * knife digital_ocean region list (options)
61
+ * knife digital_ocean image transfer (options)
62
+ **Transfer a image to another region**
63
+
64
+ * knife digital_ocean region list (options)
38
65
  **Lists the server regions/locations/data-center**
39
66
 
40
- * knife digital_ocean size list (options)
67
+ * knife digital_ocean size list (options)
41
68
  **Lists the available server sizes**
42
69
 
43
- * knife digital_ocean domain create (options)
70
+ * knife digital_ocean domain create (options)
44
71
  **Creates a domain name**
45
72
 
46
- * knife digital_ocean domain destroy (options)
73
+ * knife digital_ocean domain destroy (options)
47
74
  **Destroys a domain name**
48
75
 
49
- * knife digital_ocean domain list
76
+ * knife digital_ocean domain list (options)
50
77
  **Lists your domains added to Digital Ocean**
51
78
 
52
- * knife digital_ocean domain record create (options)
79
+ * knife digital_ocean domain record create (options)
53
80
  **Creates a record for an existing domain**
54
81
 
55
- * knife digital_ocean domain record destroy (options)
82
+ * knife digital_ocean domain record destroy (options)
56
83
  **Destroys a record for an existing domain**
57
84
 
58
- * knife digital_ocean domain record list (options)
85
+ * knife digital_ocean domain record list (options)
59
86
  **Lists records for an existing domain**
60
87
 
61
- * knife digital_ocean sshkey create (options)
88
+ * knife digital_ocean sshkey create (options)
62
89
  **Creates a ssh key for use on digital ocean**
63
90
 
64
- * knife digital_ocean sshkey destroy (options)
91
+ * knife digital_ocean sshkey destroy (options)
65
92
  **Destroys the ssh key**
66
93
 
67
- * knife digital_ocean sshkey list
94
+ * knife digital_ocean sshkey list (options)
68
95
  **Lists name + id of the uploaded known ssh keys**
69
96
 
70
- * knife digital_ocean account info
97
+ * knife digital_ocean account info (options)
71
98
  **Shows account information**
72
99
 
73
100
 
@@ -110,6 +137,7 @@ __Examples__
110
137
  --size 512mb \
111
138
  --ssh-keys 1234,1235 \
112
139
  --bootstrap \
140
+ --bootstrap-version 11.16.4-1
113
141
  --run-list "role[base],role[webserver]" \
114
142
  --secret-file "/home/user/.ssh/secret_file" \
115
143
  --ssh-port 22 \
@@ -127,6 +155,7 @@ __Syntax__
127
155
  --ssh-keys <SSH KEY-ID(s), comma-separated> \
128
156
  --ssh-port <SSH PORT> \
129
157
  --bootstrap \
158
+ --bootstrap-version <VERSION NUMBER>
130
159
  --run-list "<RUNLIST>" \
131
160
  --secret-file "<FILENAME>" \
132
161
  --private_networking
@@ -204,6 +233,54 @@ Delete droplet with id: 1824316
204
233
  Delete droplet with id: 1824317
205
234
  ```
206
235
 
236
+ #### Reboot A Droplet
237
+ ```shell
238
+ ➜ knife digital_ocean droplet reboot -I 1824315
239
+ OK
240
+ ```
241
+
242
+ #### Turn Power On/Off
243
+ ```shell
244
+ ➜ knife digital_ocean power -I 1824315 -A on
245
+ OK
246
+ ```
247
+
248
+ ```shell
249
+ ➜ knife digital_ocean power -I 1824315 -A off
250
+ OK
251
+ ```
252
+
253
+ #### Powercycle A Droplet
254
+ ```shell
255
+ ➜ knife digital_ocean powercycle -I 1824315
256
+ OK
257
+ ```
258
+
259
+ #### Rebuild A Droplet
260
+ ```shell
261
+ ➜ knife digital_ocean rebuild --droplet-id 1824315 --image-id 65420
262
+ OK
263
+ ```
264
+
265
+ #### Rename A Droplet
266
+ ```shell
267
+ ➜ knife digital_ocean rename -I 1824315 -N 'mydropletrocks.com'
268
+ OK
269
+ ```
270
+
271
+
272
+ #### Resize A Droplet
273
+ ```shell
274
+ ➜ knife digital_ocean rename -I 1824315 -s 1gb
275
+ OK
276
+ ```
277
+
278
+ #### Resize A Droplet
279
+ ```shell
280
+ ➜ knife digital_ocean snapshot -I 1824315 -N 'my-super-awesome-snapshot'
281
+ OK
282
+ ```
283
+
207
284
  ### List regions
208
285
 
209
286
  ```shell
@@ -293,6 +370,21 @@ ID Distribution Name Slug
293
370
  7556046 CoreOS CoreOS (alpha) 490.0.0 coreos-alpha
294
371
  ```
295
372
 
373
+ #### Destroy Private Images
374
+
375
+ ```shell
376
+ ➜ knife digital_ocean image destroy -I 11112
377
+ OK
378
+ ```
379
+
380
+ #### Transfer Private Images to Another Region
381
+
382
+ ```shell
383
+ ➜ knife digital_ocean image destroy -I 11112 -R ams1
384
+
385
+ ```
386
+
387
+
296
388
  ### SSH keys
297
389
 
298
390
  #### List SSH keys
@@ -374,7 +466,6 @@ UUID Email Droplet Limit Email V
374
466
  58e2e737d3b7407b042aa7f99f4da4229166f2a1 joe@example.com 10 true
375
467
  ```
376
468
 
377
-
378
469
  ## Contributing
379
470
 
380
471
  1. Fork it
@@ -396,5 +487,6 @@ Apache 2.0 (like Chef itself), see LICENSE.txt file.
396
487
 
397
488
  ## Copyright
398
489
 
399
- Copyright © 2014 [Roland Moriz](https://roland.io), [Moriz GmbH](https://moriz.de/)
490
+ Copyright © 2014 [Roland Moriz](https://roland.io), [Moriz GmbH](https://moriz.de/)
400
491
  Copyright © 2014 [Greg Fitzgerald](https://github.com/gregf)
492
+
data/Rakefile CHANGED
@@ -14,4 +14,10 @@ RuboCop::RakeTask.new(:rubocop) do |task|
14
14
  task.patterns = ['lib/**/*.rb']
15
15
  end
16
16
 
17
+ desc 'Display LOC stats'
18
+ task :loc do
19
+ puts "\n## LOC Stats"
20
+ sh 'countloc -r lib/chef/knife'
21
+ end
22
+
17
23
  task default: :spec
@@ -25,6 +25,10 @@ Gem::Specification.new do |gem|
25
25
  gem.add_development_dependency 'guard', '~> 2.8'
26
26
  gem.add_development_dependency 'guard-rspec', '~> 4.3'
27
27
  gem.add_development_dependency 'coveralls'
28
+ gem.add_development_dependency 'countloc'
29
+ gem.add_development_dependency 'simplecov'
30
+ gem.add_development_dependency 'simplecov-console'
31
+
28
32
 
29
33
  gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
30
34
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
@@ -68,6 +68,21 @@ class Chef
68
68
  key = key.to_sym
69
69
  config[key] || Chef::Config[:knife][key]
70
70
  end
71
+
72
+ def wait_for_status(result, status: 'in-progress', sleep: 3)
73
+ print 'Waiting '
74
+ while result.status == 'in-progress' do
75
+ sleep sleep
76
+ print('.')
77
+
78
+ if status == 'in-progress'
79
+ break if client.droplets.find(id: locate_config_value(:id)).status != 'in-progress'
80
+ else
81
+ break if client.droplets.find(id: locate_config_value(:id)).status == status
82
+ end
83
+ end
84
+ ui.info 'OK'
85
+ end
71
86
  end
72
87
  end
73
88
  end
@@ -21,14 +21,14 @@ class Chef
21
21
  banner 'knife digital_ocean domain create (options)'
22
22
 
23
23
  option :name,
24
- :short => '-N NAME',
25
- :long => '--name NAME',
26
- :description => 'The domain name'
24
+ short: '-N NAME',
25
+ long: '--name NAME',
26
+ description: 'The domain name'
27
27
 
28
28
  option :ip_address,
29
- :short => '-I IP Address',
30
- :long => '--ip-address address',
31
- :description => 'The ip address'
29
+ short: '-I IP Address',
30
+ long: '--ip-address address',
31
+ description: 'The ip address'
32
32
 
33
33
  def run
34
34
  $stdout.sync = true
@@ -36,20 +36,19 @@ class Chef
36
36
  validate!
37
37
 
38
38
  unless locate_config_value(:name)
39
- ui.error("Name cannot be empty. => -N <domain-name>")
39
+ ui.error('Name cannot be empty. => -N <domain-name>')
40
40
  exit 1
41
41
  end
42
42
 
43
43
  unless locate_config_value(:ip_address)
44
- ui.error("IP Address cannot be empty. => -I <ip-address>")
44
+ ui.error('IP Address cannot be empty. => -I <ip-address>')
45
45
  exit 1
46
46
  end
47
47
 
48
48
  domain = DropletKit::Domain.new ip_address: locate_config_value(:ip_address), name: locate_config_value(:name)
49
49
  result = client.domains.create domain
50
- ui.error JSON.parse(result)['message'] rescue 'OK'
50
+ ui.info 'OK' if result.class == DropletKit::Domain or ui.error JSON.parse(result)['message']
51
51
  end
52
-
53
52
  end
54
53
  end
55
54
  end
@@ -21,9 +21,9 @@ class Chef
21
21
  banner 'knife digital_ocean domain destroy (options)'
22
22
 
23
23
  option :domain,
24
- :short => '-D Name',
25
- :long => '--domain-name Name',
26
- :description => 'The domain name'
24
+ short: '-D Name',
25
+ long: '--domain-name Name',
26
+ description: 'The domain name'
27
27
 
28
28
  def run
29
29
  $stdout.sync = true
@@ -31,12 +31,12 @@ class Chef
31
31
  validate!
32
32
 
33
33
  unless locate_config_value(:domain)
34
- ui.error("Domain cannot be empty. => -D <domain-name>")
34
+ ui.error('Domain cannot be empty. => -D <domain-name>')
35
35
  exit 1
36
36
  end
37
37
 
38
38
  result = client.domains.delete(name: locate_config_value(:domain))
39
- ui.error JSON.parse(result)['message'] rescue 'OK'
39
+ ui.info 'OK' if result == true or ui.error JSON.parse(result)['message']
40
40
  end
41
41
  end
42
42
  end
@@ -31,14 +31,13 @@ class Chef
31
31
 
32
32
  domains = client.domains.all
33
33
 
34
- domains.each do |domain|
34
+ domains.sort_by(&:name).each do |domain|
35
35
  domains_list << domain.name.to_s
36
36
  domains_list << domain.ttl.to_s
37
37
  end
38
38
 
39
39
  puts ui.list(domains_list, :uneven_columns_across, 2)
40
40
  end
41
-
42
41
  end
43
42
  end
44
43
  end
@@ -20,25 +20,25 @@ class Chef
20
20
 
21
21
  banner 'knife digital_ocean domain record create (options)'
22
22
 
23
- option :domain,
24
- :short => '-D NAME',
25
- :long => '--domain-id NAME',
26
- :description => 'The domain name'
23
+ option :domain,
24
+ short: '-D NAME',
25
+ long: '--domain-id NAME',
26
+ description: 'The domain name'
27
27
 
28
28
  option :type,
29
- :short => '-T RECORD TYPE',
30
- :long => '--type RECORD TYPE',
31
- :description => 'The type of record'
29
+ short: '-T RECORD TYPE',
30
+ long: '--type RECORD TYPE',
31
+ description: 'The type of record'
32
32
 
33
33
  option :name,
34
- :short => '-N RECORD NAME',
35
- :long => '--name RECORD NAME',
36
- :description => 'The record name'
34
+ short: '-N RECORD NAME',
35
+ long: '--name RECORD NAME',
36
+ description: 'The record name'
37
37
 
38
38
  option :data,
39
- :short => '-a DATA',
40
- :long => '--data DATA',
41
- :description => 'The record data'
39
+ short: '-a DATA',
40
+ long: '--data DATA',
41
+ description: 'The record data'
42
42
 
43
43
  def run
44
44
  $stdout.sync = true
@@ -46,22 +46,22 @@ class Chef
46
46
  validate!
47
47
 
48
48
  unless locate_config_value(:domain)
49
- ui.error("Domain cannot be empty. => -D <domain-id>")
49
+ ui.error('Domain cannot be empty. => -D <domain-id>')
50
50
  exit 1
51
51
  end
52
52
 
53
53
  unless locate_config_value(:type)
54
- ui.error("Record type cannot be empty. => -T <record-type>")
54
+ ui.error('Record type cannot be empty. => -T <record-type>')
55
55
  exit 1
56
56
  end
57
57
 
58
58
  unless locate_config_value(:name)
59
- ui.error("Record name cannot be empty. => -N <record-name>")
59
+ ui.error('Record name cannot be empty. => -N <record-name>')
60
60
  exit 1
61
61
  end
62
62
 
63
63
  unless locate_config_value(:data)
64
- ui.error("Record data cannot be empty. => -d <data>")
64
+ ui.error('Record data cannot be empty. => -d <data>')
65
65
  exit 1
66
66
  end
67
67
 
@@ -71,7 +71,7 @@ class Chef
71
71
  data: locate_config_value(:data)
72
72
  )
73
73
  result = client.domain_records.create domain_record, for_domain: locate_config_value(:domain)
74
- ui.error JSON.parse(result)['message'] rescue 'OK'
74
+ ui.info 'OK' if result.class == DropletKit::DomainRecord or ui.error JSON.parse(result)['message']
75
75
  end
76
76
  end
77
77
  end