govuk-connect 0.2.1 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5a31cd142ccad0489230d52b607a835569f375fa70512443fef37b07d09faec
4
- data.tar.gz: 1df85edae1c9bc3c16af1c870be0834b06996c12ec874059ff06b7f3859bce29
3
+ metadata.gz: 716cf50c2125d2a12c992fec40538575fd7a6c40390e4e09739a2de1bd47e984
4
+ data.tar.gz: 687de70081e82f05e8d5e0bc0f7f6152942dfb6b53bdf740b21952bdd533e1b1
5
5
  SHA512:
6
- metadata.gz: 3a9d2ee8908abaa9ecf68eebac54744d45d95927c83aba9675fba8a88a344c729cff47e9e7eafb9da3557659275501af7b6408ba42ba7f2b48d9bf8b2e4ea1bd
7
- data.tar.gz: 48b1fe78c0fd719b39c93dbb47e0cbb57f7bac07647032bff796ea2f130c1a8adf2d03e473bb55d7082f10486f40da3749babdabe32e7d0e515e02ecb9dcd174
6
+ metadata.gz: 729380dae3704692181f5cac981d9fd9b40501f5ffc5a32432f8081d34c82cc1f65fc93071491a10a9b0830551ce23d6e0efb62048c51e9a2ac487f32a81a549
7
+ data.tar.gz: efc411138a7ed5bfca695f6d5a5232643c2f3afea1d5c4b37ae7618c0276b4cfd7f7f1599d4708ae4ebb689c8d04453a7ffd153d0894028703b1715f1847207f
@@ -20,6 +20,10 @@ class GovukConnect::CLI
20
20
  EXAMPLES = <<-EXAMPLES.freeze
21
21
  govuk-connect ssh --environment integration backend
22
22
 
23
+ govuk-connect scp-push --environment integration backend filename.txt /tmp/
24
+
25
+ govuk-connect scp-pull --environment integration backend /tmp/filename.txt ~/Downloads/
26
+
23
27
  govuk-connect app-console --environment staging publishing-api
24
28
 
25
29
  govuk-connect app-dbconsole -e integration whitehall_backend/whitehall
@@ -30,7 +34,7 @@ class GovukConnect::CLI
30
34
  EXAMPLES
31
35
 
32
36
  MACHINE_TARGET_DESCRIPTION = <<-DOCS.freeze
33
- The ssh, rabbitmq and sidekiq-monitoring connection types target
37
+ The ssh, scp-*, rabbitmq and sidekiq-monitoring connection types target
34
38
  machines.
35
39
 
36
40
  The machine can be specified by name, for example:
@@ -565,71 +569,7 @@ class GovukConnect::CLI
565
569
  )
566
570
  log "debug: ssh to #{target} in #{environment}"
567
571
 
568
- # Split something like aws/backend:2 in to :aws, 'backend', 2
569
- hosting, name, number = parse_hosting_name_and_number(target)
570
-
571
- if name.end_with? ".internal"
572
- ssh_target = name
573
- hosting = :aws
574
- elsif name.end_with? ".gov.uk"
575
- ssh_target = name
576
- hosting = :carrenza
577
- else
578
- # The hosting might not have been provided, so check if necessary
579
- hosting ||= hosting_for_target_and_environment(target, environment)
580
-
581
- domains = get_domains_for_node_class(
582
- name,
583
- environment,
584
- hosting,
585
- ssh_username,
586
- )
587
-
588
- if domains.length.zero?
589
- error "error: couldn't find #{name} in #{hosting}/#{environment}"
590
-
591
- node_types = govuk_node_list_classes(environment, hosting)
592
-
593
- similar_node_types = strings_similar_to(name, node_types)
594
-
595
- if similar_node_types.any?
596
- info "\ndid you mean:"
597
- similar_node_types.each { |s| info " - #{s}" }
598
- else
599
- info "\nall node types:"
600
- node_types.each { |s| info " - #{s}" }
601
- end
602
-
603
- exit 1
604
- elsif domains.length == 1
605
- ssh_target = domains.first
606
-
607
- info "There is #{bold('one machine')} to connect to"
608
- else
609
- n_machines = bold("#{domains.length} machines")
610
- info "There are #{n_machines} of this class"
611
-
612
- if number
613
- unless number.positive?
614
- print_empty_line
615
- error "error: invalid machine number '#{number}', it must be > 0"
616
- exit 1
617
- end
618
-
619
- unless number <= domains.length
620
- print_empty_line
621
- error "error: cannot connect to machine number: #{number}"
622
- exit 1
623
- end
624
-
625
- ssh_target = domains[number - 1]
626
- info "Connecting to number #{number}"
627
- else
628
- ssh_target = domains.sample
629
- info "Connecting to a random machine (number #{domains.find_index(ssh_target) + 1})"
630
- end
631
- end
632
- end
572
+ target, hosting = ssh_target(target, environment)
633
573
 
634
574
  ssh_command = [
635
575
  "ssh",
@@ -641,7 +581,7 @@ class GovukConnect::CLI
641
581
  ),
642
582
  user_at_host(
643
583
  ssh_username,
644
- ssh_target,
584
+ target,
645
585
  ),
646
586
  ]
647
587
 
@@ -669,6 +609,44 @@ class GovukConnect::CLI
669
609
  exec(*ssh_command)
670
610
  end
671
611
 
612
+ def scp(
613
+ target,
614
+ environment,
615
+ files,
616
+ push: false,
617
+ additional_arguments: []
618
+ )
619
+ log "debug: scp #{push ? 'push' : 'pull'} to #{target} in #{environment}"
620
+
621
+ target, hosting = ssh_target(target, environment)
622
+
623
+ sources = files[0, files.length - 1]
624
+ destination = files[-1]
625
+
626
+ if push
627
+ destination = "#{target}:#{destination}"
628
+ else
629
+ sources = sources.map { |source| "#{target}:#{source}" }
630
+ end
631
+
632
+ scp_command = [
633
+ "scp",
634
+ *ssh_identity_arguments,
635
+ "-o",
636
+ "ProxyJump=#{user_at_host(ssh_username, jumpbox_for_environment_and_hosting(environment, hosting))}",
637
+ "-o",
638
+ "User=#{ssh_username}",
639
+ *additional_arguments,
640
+ "--",
641
+ *sources,
642
+ destination,
643
+ ]
644
+
645
+ info "\n#{bold('Running command:')} #{scp_command.join(' ')}\n\n"
646
+
647
+ exec(*scp_command)
648
+ end
649
+
672
650
  def rabbitmq_root_password_command(hosting, environment)
673
651
  hieradata_directory = {
674
652
  aws: "puppet_aws",
@@ -829,6 +807,94 @@ class GovukConnect::CLI
829
807
  [node_class, app_name, number]
830
808
  end
831
809
 
810
+ def target_from_options(target, options)
811
+ if options.key? :hosting
812
+ hosting, name, number = parse_hosting_name_and_number(target)
813
+ if hosting
814
+ error "error: hosting specified twice"
815
+ exit 1
816
+ end
817
+
818
+ {
819
+ hosting: options[:hosting],
820
+ name: name,
821
+ number: number,
822
+ }
823
+ else
824
+ target
825
+ end
826
+ end
827
+
828
+ def ssh_target(target, environment)
829
+ # Split something like aws/backend:2 in to :aws, 'backend', 2
830
+ hosting, name, number = parse_hosting_name_and_number(target)
831
+
832
+ if name.end_with? ".internal"
833
+ target = name
834
+ hosting = :aws
835
+ elsif name.end_with? ".gov.uk"
836
+ target = name
837
+ hosting = :carrenza
838
+ else
839
+ # The hosting might not have been provided, so check if necessary
840
+ hosting ||= hosting_for_target_and_environment(target, environment)
841
+
842
+ domains = get_domains_for_node_class(
843
+ name,
844
+ environment,
845
+ hosting,
846
+ ssh_username,
847
+ )
848
+
849
+ if domains.length.zero?
850
+ error "error: couldn't find #{name} in #{hosting}/#{environment}"
851
+
852
+ node_types = govuk_node_list_classes(environment, hosting)
853
+
854
+ similar_node_types = strings_similar_to(name, node_types)
855
+
856
+ if similar_node_types.any?
857
+ info "\ndid you mean:"
858
+ similar_node_types.each { |s| info " - #{s}" }
859
+ else
860
+ info "\nall node types:"
861
+ node_types.each { |s| info " - #{s}" }
862
+ end
863
+
864
+ exit 1
865
+ elsif domains.length == 1
866
+ target = domains.first
867
+
868
+ info "There is #{bold('one machine')} to connect to"
869
+ else
870
+ n_machines = bold("#{domains.length} machines")
871
+ info "There are #{n_machines} of this class"
872
+
873
+ if number
874
+ unless number.positive?
875
+ print_empty_line
876
+ error "error: invalid machine number '#{number}', it must be > 0"
877
+ exit 1
878
+ end
879
+
880
+ unless number <= domains.length
881
+ print_empty_line
882
+ error "error: cannot connect to machine number: #{number}"
883
+ exit 1
884
+ end
885
+
886
+ target = domains[number - 1]
887
+ info "Connecting to number #{number}"
888
+ else
889
+ target = domains.sample
890
+ info "Connecting to a random machine (number #{domains.find_index(target) + 1})"
891
+ end
892
+ end
893
+ end
894
+
895
+ [target, hosting]
896
+ end
897
+
832
898
  def check_for_target(target)
833
899
  unless target
834
900
  error "error: you must specify the target\n"
@@ -848,20 +914,23 @@ class GovukConnect::CLI
848
914
 
849
915
  def types
850
916
  @types ||= {
851
- "app-console" => proc do |target, environment, args, _options|
917
+ "app-console" => proc do |target, environment, args, extra_args, _options|
852
918
  check_for_target(target)
853
919
  check_for_additional_arguments("app-console", args)
920
+ check_for_additional_arguments("app-console", extra_args)
854
921
  govuk_app_command(target, environment, "console")
855
922
  end,
856
923
 
857
- "app-dbconsole" => proc do |target, environment, args, _options|
924
+ "app-dbconsole" => proc do |target, environment, args, extra_args, _options|
858
925
  check_for_target(target)
859
926
  check_for_additional_arguments("app-dbconsole", args)
927
+ check_for_additional_arguments("app-dbconsole", extra_args)
860
928
  govuk_app_command(target, environment, "dbconsole")
861
929
  end,
862
930
 
863
- "rabbitmq" => proc do |target, environment, args, _options|
931
+ "rabbitmq" => proc do |target, environment, args, extra_args, _options|
864
932
  check_for_additional_arguments("rabbitmq", args)
933
+ check_for_additional_arguments("rabbitmq", extra_args)
865
934
 
866
935
  target ||= "rabbitmq"
867
936
 
@@ -882,8 +951,9 @@ class GovukConnect::CLI
882
951
  )
883
952
  end,
884
953
 
885
- "sidekiq-monitoring" => proc do |target, environment, args, _options|
954
+ "sidekiq-monitoring" => proc do |target, environment, args, extra_args, _options|
886
955
  check_for_additional_arguments("sidekiq-monitoring", args)
956
+ check_for_additional_arguments("sidekiq-monitoring", extra_args)
887
957
  ssh(
888
958
  target || "backend",
889
959
  environment,
@@ -891,28 +961,50 @@ class GovukConnect::CLI
891
961
  )
892
962
  end,
893
963
 
894
- "ssh" => proc do |target, environment, args, options|
964
+ "ssh" => proc do |target, environment, args, extra_args, options|
895
965
  check_for_target(target)
966
+ target = target_from_options(target, options)
896
967
 
897
- if options.key? :hosting
898
- hosting, name, number = parse_hosting_name_and_number(target)
899
- if hosting
900
- error "error: hosting specified twice"
901
- exit 1
902
- end
968
+ ssh(
969
+ target,
970
+ environment,
971
+ port_forward: options[:port_forward],
972
+ additional_arguments: [args, extra_args].flatten,
973
+ )
974
+ end,
975
+
976
+ "scp-pull" => proc do |target, environment, args, extra_args, options|
977
+ check_for_target(target)
978
+ target = target_from_options(target, options)
903
979
 
904
- target = {
905
- hosting: options[:hosting],
906
- name: name,
907
- number: number,
908
- }
980
+ if args.length < 2
981
+ error "error: need at least two filenames"
982
+ exit 1
909
983
  end
910
984
 
911
- ssh(
985
+ scp(
912
986
  target,
913
987
  environment,
914
- port_forward: options[:port_forward],
915
- additional_arguments: args,
988
+ args,
989
+ additional_arguments: extra_args,
990
+ )
991
+ end,
992
+
993
+ "scp-push" => proc do |target, environment, args, extra_args, options|
994
+ check_for_target(target)
995
+ target = target_from_options(target, options)
996
+
997
+ if args.length < 2
998
+ error "error: need at least two filenames"
999
+ exit 1
1000
+ end
1001
+
1002
+ scp(
1003
+ target,
1004
+ environment,
1005
+ args,
1006
+ push: true,
1007
+ additional_arguments: extra_args,
916
1008
  )
917
1009
  end,
918
1010
  }
@@ -921,23 +1013,21 @@ class GovukConnect::CLI
921
1013
  def main(argv)
922
1014
  check_ruby_version_greater_than(required_major: 2, required_minor: 0)
923
1015
 
1016
+ extra_arguments_after_double_dash = []
1017
+
924
1018
  double_dash_index = argv.index "--"
925
1019
  if double_dash_index
926
- # This is used in the case of passing extra options to ssh, the --
927
- # acts as a separator, so to avoid optparse interpreting those
928
- # options, split argv around -- before parsing the options
929
- rest = argv[double_dash_index + 1, argv.length]
1020
+ # This is used in the case of passing extra options to ssh and
1021
+ # scp, the -- acts as a separator, so to avoid optparse
1022
+ # interpreting those as options, split argv around -- before
1023
+ # parsing the options
1024
+ extra_arguments_after_double_dash = argv[double_dash_index + 1, argv.length]
930
1025
  argv = argv[0, double_dash_index]
931
-
932
- options = parse_options(argv)
933
-
934
- type, target = argv
935
- else
936
- options = parse_options(argv)
937
-
938
- type, target, *rest = argv
939
1026
  end
940
1027
 
1028
+ govuk_connect_options = parse_options(argv)
1029
+ type, target, *extra_arguments_before_double_dash = argv
1030
+
941
1031
  unless type
942
1032
  error "error: you must specify the connection type\n"
943
1033
 
@@ -970,7 +1060,7 @@ class GovukConnect::CLI
970
1060
  exit 1
971
1061
  end
972
1062
 
973
- environment = options[:environment]&.to_sym
1063
+ environment = govuk_connect_options[:environment]&.to_sym
974
1064
 
975
1065
  unless environment
976
1066
  error "error: you must specify the environment\n"
@@ -986,7 +1076,13 @@ class GovukConnect::CLI
986
1076
  exit 1
987
1077
  end
988
1078
 
989
- handler.call(target, environment, rest, options)
1079
+ handler.call(
1080
+ target,
1081
+ environment,
1082
+ extra_arguments_before_double_dash,
1083
+ extra_arguments_after_double_dash,
1084
+ govuk_connect_options,
1085
+ )
990
1086
  rescue Interrupt
991
1087
  # Handle SIGTERM without printing a stacktrace
992
1088
  exit 1
@@ -1,3 +1,3 @@
1
1
  module GovukConnect
2
- VERSION = "0.2.1".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk-connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Government Digital Service
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-15 00:00:00.000000000 Z
11
+ date: 2020-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control