enfcli 4.1.0.pre.beta → 4.2.1.pre.alpha

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27d832f6ee49be44d9463b1b77931d15db08f79f6d382c1bc243635ef9eca137
4
- data.tar.gz: 070eabadf3b810b47c948dd5ca84cc362852dde237dba5a95a7e4e90e011f8b0
3
+ metadata.gz: 27b28906253cb5aa863c719da49ea29361254f44d7cc638e332d531f404e3887
4
+ data.tar.gz: b6c231170699644a0628d9911368b822214b47916c61b66424384d19b5eb48fd
5
5
  SHA512:
6
- metadata.gz: afc068399c4e7477a16388c3ead24346520823cb214b19befe9a4a4d58a19f14b4f45868b31c66b7841c24073970241fb81b68f54e5bc23534d547e586436de4
7
- data.tar.gz: 3d9e53a84414a42d17e35c8c01852af895a149d5e906000d3e84fa7282150d49542a91c130c73b35b8a010139771adcac0267a31991686799b62346f42daf6ba
6
+ metadata.gz: 84a41a3805664bf9e341d6a545daf92bc82c1271f5ccb92695808ae9e4737ecd8c148259d904f28f0bdbf65a8e6f34333c503adccf39b63c261d7b6bb1976d41
7
+ data.tar.gz: 94706731090498b60bde0dcc0181cabf7ba7bddd9088c879cc049f4f7e87990bdf5e5bc05774a61506f3c3b9cffd1dff0314b75fb9fb2b65c43c7fa7875e2549
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- enfcli (4.1.0.pre.beta)
4
+ enfcli (4.2.1.pre.alpha)
5
5
  clipboard
6
6
  ffi
7
7
  readline
@@ -32,13 +32,13 @@ GEM
32
32
  io-console (0.5.6)
33
33
  mime-types (3.3.1)
34
34
  mime-types-data (~> 3.2015)
35
- mime-types-data (3.2019.1009)
35
+ mime-types-data (3.2020.0425)
36
36
  netrc (0.11.0)
37
37
  public_suffix (4.0.3)
38
38
  rake (10.5.0)
39
39
  readline (0.0.2)
40
40
  reline
41
- reline (0.1.3)
41
+ reline (0.1.4)
42
42
  io-console (~> 0.5)
43
43
  rest-client (2.1.0)
44
44
  http-accept (>= 1.7.0, < 2.0)
data/lib/enfapi.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2018 Xaptum,Inc
2
+ # Copyright 2020 Xaptum,Inc
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -284,6 +284,89 @@ module EnfApi
284
284
  json = EnfApi.to_json(profile_updates)
285
285
  EnfApi::API.instance.put "/api/captive/v1/profile/#{id}", json
286
286
  end
287
+
288
+ # Get the list of devices
289
+ ## NO_TEST
290
+ def list_firmware_images()
291
+ url = "/api/captive/v1/firmware/release"
292
+ EnfApi::API.instance.get url
293
+ end
294
+
295
+ # Upload the firmware image
296
+ # Current version sends an empty body - captive server doesn't support
297
+ # sending the binary image yet.
298
+ ## NO_TEST
299
+ def upload_firmware_image(version, image_name)
300
+ url = "/api/captive/v1/firmware/release/#{version}/#{image_name}"
301
+ EnfApi::API.instance.put url
302
+ end
303
+
304
+ # gets the details for a specific firmware version
305
+ ## NO_TEST
306
+ def get_firmware_info(version)
307
+ url = "/api/captive/v1/firmware/release/#{version}"
308
+ EnfApi::API.instance.get url
309
+ end
310
+
311
+ # creates a new schedule object via POST
312
+ ## NO_TEST
313
+ def create_schedule(sched_hash)
314
+ json = EnfApi.to_json(sched_hash)
315
+ EnfApi::API.instance.post "/api/captive/v1/schedule", json
316
+ end
317
+
318
+ # GETs a list of all existing schedules
319
+ ## NO_TEST
320
+ def list_schedules
321
+ EnfApi::API.instance.get "/api/captive/v1/schedule"
322
+ end
323
+
324
+ # GETs the details of a specific schedule
325
+ ## NO_TEST
326
+ def get_schedule(id)
327
+ EnfApi::API.instance.get "/api/captive/v1/schedule/#{id}"
328
+ end
329
+
330
+ # update the details of a specific schedule
331
+ ## NO_TEST
332
+ def update_schedule(id, sched_hash)
333
+ json = EnfApi.to_json(sched_hash)
334
+ url = "/api/captive/v1/schedule/#{id}"
335
+ EnfApi::API.instance.put url, json
336
+ end
337
+
338
+ # DELETEs the specified schedule
339
+ ## NO_TEST
340
+ def delete_schedule(id)
341
+ EnfApi::API.instance.delete "/api/captive/v1/schedule/#{id}"
342
+ end
343
+
344
+ # GET the list of existing update objects
345
+ ## NO_TEST
346
+ def list_firmware_updates()
347
+ EnfApi::API.instance.get "/api/captive/v1/firmware/update"
348
+ end
349
+
350
+ # GET details of a specified firmware update task
351
+ ## NO_TEST
352
+ def get_firmware_update(update_id)
353
+ EnfApi::API.instance.get "/api/captive/v1/firmware/update/#{update_id}"
354
+ end
355
+
356
+ # POSTs a new firmware-udpate object
357
+ ## NO_TEST
358
+ def create_firmware_update(update_hash)
359
+ json = EnfApi.to_json(update_hash)
360
+ EnfApi::API.instance.post "/api/captive/v1/firmware/update", json
361
+ end
362
+
363
+ # uses PUT to modify an existing firmware update task
364
+ ## NO_TEST
365
+ def modify_firmware_update(update_id, update_hash)
366
+ url = "/api/captive/v1/firmware/update/#{update_id}"
367
+ json = EnfApi.to_json(update_hash)
368
+ EnfApi::API.instance.put url, json
369
+ end
287
370
  end
288
371
 
289
372
  class NetworkManager
@@ -569,6 +652,13 @@ module EnfApi
569
652
  rescue JSON::ParserError => e
570
653
  raise EnfApi::ERROR, "Not Found"
571
654
  end
655
+ when 500
656
+ begin
657
+ JSON.parse(response.body)
658
+ raise EnfApi::ERROR, api_error_msg(from_json(response.body))
659
+ rescue JSON::ParserError => e
660
+ raise EnfApi::ERROR, "Server error was received without details."
661
+ end
572
662
  else
573
663
  raise EnfApi::ERROR, "Unexpected error! Please try again!"
574
664
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # Copyright 2018-2019 Xaptum,Inc
4
+ # Copyright 2018-2020 Xaptum,Inc
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -278,6 +278,10 @@ module EnfCli
278
278
  desc: "secure-host or passthrough"
279
279
  method_option :'wifi-id', type: :string, default: nil, banner: "WIFI-ID",
280
280
  desc: "WIFI-ID is the UUID of the wifi record that the profile will use. wifi record must already exist"
281
+ method_option :'update-id', type: :string, default: nil,
282
+ banner: "UPDATE-ID",
283
+ desc: "UPDATE-ID is the UUID of the firmware update record. " \
284
+ "The firmware-update record must already exist."
281
285
 
282
286
  def create_profile
283
287
  try_with_rescue_in_session do
@@ -293,6 +297,12 @@ module EnfCli
293
297
  new_profile_hash[:config][:wifi][:id] = wifi
294
298
  end
295
299
 
300
+ fw_update = options[:'update-id']
301
+ if fw_update
302
+ new_profile_hash[:config][:firmware] = {}
303
+ new_profile_hash[:config][:firmware][:id] = fw_update if fw_update
304
+ end
305
+
296
306
  # send the POST to create a new profile
297
307
  profile = EnfApi::Captive.instance.create_profile new_profile_hash
298
308
  display_profile profile
@@ -341,6 +351,10 @@ module EnfCli
341
351
  desc: "secure-host or passthrough"
342
352
  method_option :'wifi-id', type: :string, default: nil, banner: "WIFI-ID",
343
353
  desc: "WIFI-ID is the UUID of the wifi record that the profile will use. wifi record must already exist"
354
+ method_option :'update-id', type: :string, default: nil,
355
+ banner: "UPDATE-ID",
356
+ desc: "UPDATE-ID is the UUID of the firmware update record. " \
357
+ "The firmware-update record must already exist."
344
358
 
345
359
  def update_profile
346
360
  try_with_rescue_in_session do
@@ -348,23 +362,250 @@ module EnfCli
348
362
  name = options[:'profile-name']
349
363
  mode = options[:'device-mode']
350
364
  wifi_id = options[:'wifi-id']
365
+ fw_update = options[:'update-id']
351
366
 
352
- raise "At least one option needs to change." if name == nil && mode == nil && wifi_id == nil
367
+ raise "At least one option needs to change." if name == nil && mode == nil && wifi_id == nil && fw_update == nil
353
368
 
354
369
  update_hash = {}
355
370
  update_hash[:name] = name if name
356
- update_hash[:config] = {} if wifi_id || mode
371
+ update_hash[:config] = {} if wifi_id || mode || fw_update
357
372
  update_hash[:config][:mode] = mode if mode
358
373
  if wifi_id
359
374
  update_hash[:config][:wifi] = {}
360
375
  update_hash[:config][:wifi][:id] = wifi_id
361
376
  end
362
377
 
378
+ if fw_update
379
+ update_hash[:config][:firmware] = {}
380
+ update_hash[:config][:firmware][:id] = fw_update
381
+ end
363
382
  profile = EnfApi::Captive.instance.update_profile id, update_hash
364
383
  display_profile profile
365
384
  end
366
385
  end
367
386
 
387
+ desc "list-firmware-images",
388
+ "Lists all of the available versions of the firmware"
389
+
390
+ def list_firmware_images
391
+ try_with_rescue_in_session do
392
+ data = EnfApi::Captive.instance.list_firmware_images
393
+ display_firmware_image_list data
394
+ end
395
+ end
396
+
397
+ desc "upload-firmware-image",
398
+ "Uploads a new firmware image. Each version will have multiple " \
399
+ "images -- one for each type of hardware. \nNOTE: This version " \
400
+ "doesn't actually upload the file, it merely informs the server of " \
401
+ "its existance."
402
+ method_option :'image-file', required: true, type: :string,
403
+ banner: "<file>", desc: "<file> is the firmware binary image."
404
+ method_option :version, required: true, type: :string,
405
+ banner: "VERSION",
406
+ desc: "VERSION is the release version."
407
+ method_option :'image-name', type: :string, default: nil, banner: "NAME",
408
+ desc: "NAME is the name to associate with the firmware " \
409
+ "image. This is usually the generated filename. " \
410
+ "Defaults to the base name of <file>"
411
+
412
+ def upload_firmware_image
413
+ try_with_rescue_in_session do
414
+ filename = options[:'image-file']
415
+ version = options[:version]
416
+ image_name = options[:'image-name']
417
+
418
+ temp_img_name = File.basename(filename)
419
+ image_name ||= temp_img_name
420
+
421
+ raise "image-name does not match image-file" if temp_img_name != image_name
422
+
423
+ # This version PUTs an empty body
424
+ resp = EnfApi::Captive.instance.upload_firmware_image version, image_name
425
+
426
+ if (resp.code == 200)
427
+ say "Upload complete."
428
+ else
429
+ say "Upload failed with code #{resp.code}"
430
+ end
431
+ end
432
+ end
433
+
434
+ desc "get-firmware-info",
435
+ "Prints details of an existing firmware version."
436
+ method_option :version, required: true, type: :string,
437
+ banner: "VERSION", desc: "VERSION is the release version."
438
+
439
+ def get_firmware_info
440
+ try_with_rescue_in_session do
441
+ version = options[:version]
442
+
443
+ fw_info = EnfApi::Captive.instance.get_firmware_info version
444
+
445
+ display_firmware_detail fw_info
446
+ end
447
+ end
448
+
449
+ desc "create-schedule",
450
+ "Creates a schedule object that will be used to determine when a " \
451
+ "device or group of devices may be upgraded. The schedule will be " \
452
+ "uploaded from a JSON-formatted file."
453
+ method_option :schedule, required: true, type: :string,
454
+ banner: "<file>",
455
+ desc: "<file> is a JSON file containing the desired schedule."
456
+
457
+ def create_schedule
458
+ try_with_rescue_in_session do
459
+ filename = options[:schedule]
460
+
461
+ # reading the whole file - shouldn't get more than a few KB
462
+ content = File.read filename
463
+ sched_hash = JSON.parse(content)
464
+
465
+ resp_data = EnfApi::Captive.instance.create_schedule sched_hash
466
+ display_schedule_detail resp_data
467
+ end
468
+ end
469
+
470
+ desc "list-schedules",
471
+ "Prints a summary list of all existing schedules."
472
+
473
+ def list_schedules
474
+ try_with_rescue_in_session do
475
+ sched_list = EnfApi::Captive.instance.list_schedules
476
+ display_schedule_list sched_list
477
+ end
478
+ end
479
+
480
+ desc "get-schedule",
481
+ "Prints the detail of a specific, existing schedule."
482
+ method_option :'schedule-id', type: :string, required: true, banner: "ID",
483
+ desc: "ID is the system-assigned UUID of the schedule " \
484
+ "to retrieve."
485
+
486
+ def get_schedule
487
+ try_with_rescue_in_session do
488
+ sched_id = options[:'schedule-id']
489
+ sched_data = EnfApi::Captive.instance.get_schedule sched_id
490
+ display_schedule_detail sched_data
491
+ end
492
+ end
493
+
494
+ desc "update-schedule",
495
+ "Modifies an existing schedule by uploading an updated schedule in " \
496
+ "the form of a JSON file."
497
+ method_option :'schedule-id', type: :string, required: true, banner: "ID",
498
+ desc: "ID is the UUID of the schedule to update."
499
+ method_option :schedule, type: :string, required: true, bannder: "<file>",
500
+ desc: "<file> is a JSON file containing the desired schedule."
501
+
502
+ def update_schedule
503
+ try_with_rescue_in_session do
504
+ sched_id = options[:'schedule-id']
505
+ filename = options[:schedule]
506
+
507
+ # read in whole schedule file
508
+ content = File.read filename
509
+ sched_hash = JSON.parse(content)
510
+
511
+ resp_data = EnfApi::Captive.instance.update_schedule sched_id, sched_hash
512
+ display_schedule_detail resp_data
513
+ end
514
+ end
515
+
516
+ desc "delete-schedule",
517
+ "Deletes the specified, existing schedule."
518
+ method_option :'schedule-id', type: :string, required: true, banner: "ID",
519
+ desc: "ID is the system-assigned UUID of the schedule " \
520
+ "to delete."
521
+
522
+ def delete_schedule
523
+ try_with_rescue_in_session do
524
+ sched_id = options[:'schedule-id']
525
+
526
+ # get the name of the schedule
527
+ resp = EnfApi::Captive.instance.get_schedule(sched_id)
528
+ name = resp[:name]
529
+
530
+ resp = EnfApi::Captive.instance.delete_schedule sched_id
531
+
532
+ if (resp.code == 200)
533
+ say "Successfully deleted schedule named: #{name}"
534
+ elsif (resp.code == 409)
535
+ say "Schedule #{name} is being used by pending updates and cannot be deleted."
536
+ else
537
+ say "Failed to delete schedule #{name} with code #{resp.code}"
538
+ end
539
+ end
540
+ end
541
+
542
+ desc "list-firmware-updates",
543
+ "Lists the existing firmware update tasks."
544
+
545
+ def list_firmware_updates
546
+ try_with_rescue_in_session do
547
+ updates_list = EnfApi::Captive.instance.list_firmware_updates
548
+ display_updates_list updates_list
549
+ end
550
+ end
551
+
552
+ desc "get-firmware-update",
553
+ "Prints the details of the specified firmware update task."
554
+ method_option :'update-id', type: :string, required: true, banner: "ID",
555
+ desc: "ID is the UUID of the firmware update task"
556
+
557
+ def get_firmware_update
558
+ try_with_rescue_in_session do
559
+ update_id = options[:'update-id']
560
+
561
+ update_data = EnfApi::Captive.instance.get_firmware_update update_id
562
+ display_update_detail update_data
563
+ end
564
+ end
565
+
566
+ desc "create-firmware-update",
567
+ "Creates a firmware-update task that the system will use to update " \
568
+ "router-card firmware as prescribed in the specified JSON file."
569
+ method_option :update, type: :string, required: true, banner: "<file>",
570
+ desc: "<file> is a JSON file containing the details of " \
571
+ "the update task."
572
+
573
+ def create_firmware_update
574
+ try_with_rescue_in_session do
575
+ filename = options[:update]
576
+
577
+ # reading the whole file - shouldn't get more than a few KB
578
+ content = File.read filename
579
+ update_hash = JSON.parse(content)
580
+
581
+ resp_data = EnfApi::Captive.instance.create_firmware_update update_hash
582
+ display_update_detail resp_data
583
+ end
584
+ end
585
+
586
+ desc "modify-firmware-update",
587
+ "Modifies an existing firmware-update task with the information " \
588
+ "contained in the specified JSON file"
589
+ method_option :'update-id', type: :string, required: true, banner: "ID",
590
+ desc: "ID is the UUID of the firmware update task to be modified."
591
+ method_option :update, type: :string, required: true, banner: "<file>",
592
+ desc: "<file> is a JSON file containing the details of " \
593
+ "the update task."
594
+
595
+ def modify_firmware_update
596
+ try_with_rescue_in_session do
597
+ update_id = options[:'update-id']
598
+ filename = options[:update]
599
+
600
+ # reading the whole file - shouldn't get more than a few KB
601
+ content = File.read filename
602
+ update_hash = JSON.parse(content)
603
+
604
+ resp_data = EnfApi::Captive.instance.modify_firmware_update update_id, update_hash
605
+ display_update_detail resp_data
606
+ end
607
+ end
608
+
368
609
  #########################################################################
369
610
  #
370
611
  # Helper functions
@@ -613,7 +854,6 @@ module EnfCli
613
854
  # [hash[:serial_number], hash[:device_name], hash[:device_address],
614
855
  # hash[:status][:router_mode], hash[:status][:wifi][:connected],
615
856
  # hash[:status][:wifi][:SSID]]
616
-
617
857
  render_table(headings, rows)
618
858
  end
619
859
 
@@ -623,11 +863,20 @@ module EnfCli
623
863
  def display_profile(profile, summary = false)
624
864
  indent = summary ? " " : ""
625
865
 
866
+ firmware = profile[:config][:firmware]
867
+ fw_id = "< not configured >"
868
+ if firmware
869
+ fw_id = firmware[:id]
870
+ fw_version = firmware[:version]
871
+ end
872
+
626
873
  say indent + "Name : #{profile[:name]}", nil, true
627
874
  say indent + "Profile ID : #{profile[:id]}", nil, true
628
875
  say indent + "Configuration version : #{profile[:config][:version]}", nil, true
876
+ say indent + "Firmware Update ID : #{fw_id}", nil, true
629
877
  unless summary
630
- say "Mode : #{profile[:config][:mode]}", nil, true
878
+ say indent + " Update version : #{fw_version}", nil, true if fw_version
879
+ say indent + "Mode : #{profile[:config][:mode]}", nil, true
631
880
  display_wifi_summary profile[:config][:wifi]
632
881
  end
633
882
  end
@@ -654,13 +903,114 @@ module EnfCli
654
903
  # display the profile summary list
655
904
  #
656
905
  def display_profile_list(profiles)
657
- headings = ["Profile Name", "Profile ID", "Version"]
906
+ headings = ["Profile Name", "Profile ID", "Version", "Mode", "Wifi ID", "Firmware Update ID"]
658
907
  rows = profiles.map do |hash|
659
- [hash[:name], hash[:id], hash[:config][:version]]
908
+ config = hash[:config]
909
+ fw_id = config[:firmware] ? config[:firmware][:id] : "none"
910
+ [hash[:name], hash[:id], config[:version], config[:mode],
911
+ config[:wifi][:id], fw_id]
660
912
  end
913
+ render_table(headings, rows)
914
+ end
661
915
 
916
+ #
917
+ # Displays the list of firmware releases
918
+ #
919
+ def display_firmware_image_list(images)
920
+ headings = ["Firmware Version"]
921
+ rows = images.map do |element|
922
+ [element[:version]]
923
+ end
662
924
  render_table(headings, rows)
663
925
  end
926
+
927
+ #
928
+ # Displays firmware detail
929
+ #
930
+ def display_firmware_detail(fw_info)
931
+ version = fw_info[:version] || "< not available >"
932
+ images = fw_info[:images]
933
+
934
+ say "Release version: #{version}"
935
+ display_image_list images
936
+ end
937
+
938
+ #
939
+ # Displays the list of images available for a release version.
940
+ #
941
+ def display_image_list(images)
942
+ headings = ["Image Name", "Hardware Model", "Update Type", "SHA256"]
943
+ rows = images.map do |hash|
944
+ [hash[:name], hash[:model], hash[:type], hash[:sha256]]
945
+ end
946
+ render_table(headings, rows)
947
+ end
948
+
949
+ #
950
+ # Displays the full SCHEDULE object detail
951
+ #
952
+ def display_schedule_detail(sched_data)
953
+ name = sched_data[:name]
954
+ id = sched_data[:id]
955
+ domain = sched_data[:domain]
956
+ times = sched_data[:times]
957
+
958
+ say "Schedule Name : #{name}", nil, true
959
+ say "Shedule ID : #{id}", nil, true
960
+ say "domain : #{domain}", nil, true
961
+ say "Times:", nil, true
962
+ display_time_list(times)
963
+ end
964
+
965
+ #
966
+ # Displays the list of times in a schedule as a table
967
+ #
968
+ def display_time_list(times)
969
+ headings = ["Name", "year", "Month", "Date", "Weekday", "Hour",
970
+ "Minute", "id"]
971
+ rows = times.map do |hash|
972
+ [hash[:name], hash[:year], hash[:month], hash[:day_of_month],
973
+ hash[:day_of_week], hash[:hour], hash[:minute], hash[:id]]
974
+ end
975
+ render_table(headings, rows)
976
+ end
977
+
978
+ #
979
+ # Displays a list of schedules
980
+ #
981
+ def display_schedule_list(sched_list)
982
+ headings = ["Name", "ID"]
983
+ rows = sched_list.map do |hash|
984
+ [hash[:name], hash[:id]]
985
+ end
986
+ render_table(headings, rows)
987
+ end
988
+
989
+ #
990
+ # Displays a list of firmware updates
991
+ #
992
+ def display_updates_list(updates_list)
993
+ headings = ["Update ID", "Update Version"]
994
+ rows = updates_list.map do |hash|
995
+ [hash[:id], hash[:version]]
996
+ end
997
+ render_table(headings, rows)
998
+ end
999
+
1000
+ #
1001
+ # Displays detail of a specific firmware update task
1002
+ #
1003
+ def display_update_detail(update_data)
1004
+ id = update_data[:id]
1005
+ sched_id = update_data[:schedule_id]
1006
+ version = update_data[:version]
1007
+ percent = update_data[:update_percentage]
1008
+
1009
+ say "Update Task ID : #{id}"
1010
+ say "Schedule ID : #{sched_id}"
1011
+ say "Firmware Version : #{version}"
1012
+ say "Percent of devices to update : #{percent}"
1013
+ end
664
1014
  end
665
1015
  end
666
1016
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2018 Xaptum,Inc
2
+ # Copyright 2018-2020 Xaptum,Inc
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -14,5 +14,5 @@
14
14
  # limitations under the License.
15
15
  #
16
16
  module EnfCli
17
- VERSION = "4.1.0-beta"
17
+ VERSION = "4.2.1-alpha"
18
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enfcli
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0.pre.beta
4
+ version: 4.2.1.pre.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Venkatakumar Srinivasan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-24 00:00:00.000000000 Z
11
+ date: 2020-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor