govuk-connect 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/govuk_connect/cli.rb +196 -100
- data/lib/govuk_connect/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 716cf50c2125d2a12c992fec40538575fd7a6c40390e4e09739a2de1bd47e984
|
4
|
+
data.tar.gz: 687de70081e82f05e8d5e0bc0f7f6152942dfb6b53bdf740b21952bdd533e1b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 729380dae3704692181f5cac981d9fd9b40501f5ffc5a32432f8081d34c82cc1f65fc93071491a10a9b0830551ce23d6e0efb62048c51e9a2ac487f32a81a549
|
7
|
+
data.tar.gz: efc411138a7ed5bfca695f6d5a5232643c2f3afea1d5c4b37ae7618c0276b4cfd7f7f1599d4708ae4ebb689c8d04453a7ffd153d0894028703b1715f1847207f
|
data/lib/govuk_connect/cli.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
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
|
-
|
905
|
-
|
906
|
-
|
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
|
-
|
985
|
+
scp(
|
912
986
|
target,
|
913
987
|
environment,
|
914
|
-
|
915
|
-
additional_arguments:
|
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
|
927
|
-
# acts as a separator, so to avoid optparse
|
928
|
-
# options, split argv around -- before
|
929
|
-
|
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 =
|
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(
|
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
|
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.
|
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-
|
11
|
+
date: 2020-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: climate_control
|