morpheus-cli 5.3.3 → 5.3.4
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 +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +12 -0
- data/lib/morpheus/api/clouds_interface.rb +4 -11
- data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
- data/lib/morpheus/api/load_balancer_profiles_interface.rb +10 -0
- data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +4 -4
- data/lib/morpheus/api/network_routers_interface.rb +21 -0
- data/lib/morpheus/api/network_servers_interface.rb +42 -0
- data/lib/morpheus/api/rest_interface.rb +2 -1
- data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
- data/lib/morpheus/cli/cli_command.rb +2 -1
- data/lib/morpheus/cli/cloud_resource_pools_command.rb +1 -1
- data/lib/morpheus/cli/clouds.rb +22 -40
- data/lib/morpheus/cli/hosts.rb +0 -1
- data/lib/morpheus/cli/instances.rb +111 -7
- data/lib/morpheus/cli/invoices_command.rb +42 -38
- data/lib/morpheus/cli/library_option_lists_command.rb +3 -3
- data/lib/morpheus/cli/load_balancer_pools.rb +111 -0
- data/lib/morpheus/cli/load_balancer_virtual_servers.rb +136 -0
- data/lib/morpheus/cli/load_balancers.rb +0 -155
- data/lib/morpheus/cli/mixins/load_balancers_helper.rb +2 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +32 -11
- data/lib/morpheus/cli/mixins/rest_command.rb +53 -37
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +488 -0
- data/lib/morpheus/cli/network_routers_command.rb +291 -7
- data/lib/morpheus/cli/network_scopes_command.rb +442 -0
- data/lib/morpheus/cli/networks_command.rb +2 -2
- data/lib/morpheus/cli/option_types.rb +20 -0
- data/lib/morpheus/cli/subnets_command.rb +7 -2
- data/lib/morpheus/cli/tasks.rb +25 -2
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +2 -0
- data/lib/morpheus/cli.rb +9 -1
- metadata +9 -2
@@ -17,6 +17,7 @@ class Morpheus::Cli::NetworkRoutersCommand
|
|
17
17
|
register_subcommands :add_route, :remove_route, :routes
|
18
18
|
register_subcommands :update_permissions
|
19
19
|
register_subcommands :add_nat, :update_nat, :remove_nat, :nats, :nat
|
20
|
+
register_subcommands :add_bgp_neighbor, :update_bgp_neighbor, :remove_bgp_neighbor, :bgp_neighbors, :bgp_neighbor
|
20
21
|
|
21
22
|
def initialize()
|
22
23
|
end
|
@@ -313,7 +314,7 @@ class Morpheus::Cli::NetworkRoutersCommand
|
|
313
314
|
server_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkServer', 'type' => 'select', 'fieldLabel' => 'Network Server', 'required' => true, 'optionSource' => 'networkServer'}], options[:options], @api_client, params, nil, true)['networkServer']
|
314
315
|
server = {'id' => server_id}
|
315
316
|
end
|
316
|
-
router['networkServer'] = {'id' => server['id']}
|
317
|
+
params['router']['networkServer'] = router['networkServer'] = {'id' => server['id']}
|
317
318
|
params['networkServerId'] = server['id']
|
318
319
|
else
|
319
320
|
# prompt cloud
|
@@ -1517,11 +1518,11 @@ class Morpheus::Cli::NetworkRoutersCommand
|
|
1517
1518
|
options = {}
|
1518
1519
|
query_params = {}
|
1519
1520
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1520
|
-
opts.banner = subcommand_usage("[router] [
|
1521
|
+
opts.banner = subcommand_usage("[router] [route]")
|
1521
1522
|
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
|
1522
1523
|
opts.footer = "Delete a network router route.\n" +
|
1523
|
-
|
1524
|
-
|
1524
|
+
"[router] is required. This is the name or id of an existing network router."
|
1525
|
+
"[route] is required. This is the name or id of an existing network router route."
|
1525
1526
|
end
|
1526
1527
|
optparse.parse!(args)
|
1527
1528
|
if args.count != 2
|
@@ -1628,11 +1629,11 @@ class Morpheus::Cli::NetworkRoutersCommand
|
|
1628
1629
|
def nat(args)
|
1629
1630
|
options = {}
|
1630
1631
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1631
|
-
opts.banner = subcommand_usage("[router] [
|
1632
|
+
opts.banner = subcommand_usage("[router] [nat]")
|
1632
1633
|
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
1633
1634
|
opts.footer = "Display network router firewall rule details." + "\n" +
|
1634
1635
|
"[router] is required. This is the name or id of a network router.\n" +
|
1635
|
-
"[
|
1636
|
+
"[nat] is required. This is the name or id of a NAT.\n"
|
1636
1637
|
end
|
1637
1638
|
|
1638
1639
|
optparse.parse!(args)
|
@@ -1887,6 +1888,268 @@ class Morpheus::Cli::NetworkRoutersCommand
|
|
1887
1888
|
end
|
1888
1889
|
end
|
1889
1890
|
|
1891
|
+
def bgp_neighbors(args)
|
1892
|
+
options = {}
|
1893
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1894
|
+
opts.banner = subcommand_usage("[router]")
|
1895
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
1896
|
+
opts.footer = "List network router BGP neighbors." + "\n" +
|
1897
|
+
"[router] is required. This is the name or id of a network router."
|
1898
|
+
end
|
1899
|
+
|
1900
|
+
optparse.parse!(args)
|
1901
|
+
connect(options)
|
1902
|
+
|
1903
|
+
if args.count < 1
|
1904
|
+
puts optparse
|
1905
|
+
return 1
|
1906
|
+
end
|
1907
|
+
_bgp_neighbors(args[0], options)
|
1908
|
+
end
|
1909
|
+
|
1910
|
+
def _bgp_neighbors(router_id, options)
|
1911
|
+
@network_routers_interface.setopts(options)
|
1912
|
+
if options[:dry_run]
|
1913
|
+
if args[0].to_s =~ /\A\d{1,}\Z/
|
1914
|
+
print_dry_run @network_routers_interface.dry.get(router_id.to_i)
|
1915
|
+
else
|
1916
|
+
print_dry_run @network_routers_interface.dry.list({name:router_id})
|
1917
|
+
end
|
1918
|
+
return
|
1919
|
+
end
|
1920
|
+
router = find_router(router_id)
|
1921
|
+
if router.nil?
|
1922
|
+
return 1
|
1923
|
+
end
|
1924
|
+
|
1925
|
+
if router['type']['hasBgp']
|
1926
|
+
json_response = {'networkRouterBgpNeighbors' => router['bgpNeighbors']}
|
1927
|
+
render_response(json_response, options, 'networkRouterBgpNeighbor') do
|
1928
|
+
print_h1 "Network Router BGP Neighbors For: #{router['name']}"
|
1929
|
+
print cyan
|
1930
|
+
print_bgp_neighbors(router)
|
1931
|
+
end
|
1932
|
+
else
|
1933
|
+
print_red_alert "BGP not supported for #{router['type']['name']}"
|
1934
|
+
end
|
1935
|
+
print reset
|
1936
|
+
end
|
1937
|
+
|
1938
|
+
def bgp_neighbor(args)
|
1939
|
+
options = {}
|
1940
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1941
|
+
opts.banner = subcommand_usage("[router] [BGP neighbor]")
|
1942
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
1943
|
+
opts.footer = "Display details on network router BGP neighbor." + "\n" +
|
1944
|
+
"[router] is required. This is the name or id of a network router.\n" +
|
1945
|
+
"[BGP neighbor] is required. This is the id of a BGP neighbor.\n"
|
1946
|
+
end
|
1947
|
+
|
1948
|
+
optparse.parse!(args)
|
1949
|
+
connect(options)
|
1950
|
+
|
1951
|
+
if args.count < 2
|
1952
|
+
puts optparse
|
1953
|
+
return 1
|
1954
|
+
end
|
1955
|
+
|
1956
|
+
@network_routers_interface.setopts(options)
|
1957
|
+
if options[:dry_run]
|
1958
|
+
if args[0].to_s =~ /\A\d{1,}\Z/
|
1959
|
+
print_dry_run @network_routers_interface.dry.get(args[0].to_i)
|
1960
|
+
else
|
1961
|
+
print_dry_run @network_routers_interface.dry.list({name:args[0]})
|
1962
|
+
end
|
1963
|
+
return
|
1964
|
+
end
|
1965
|
+
router = find_router(args[0])
|
1966
|
+
if router.nil?
|
1967
|
+
return 1
|
1968
|
+
end
|
1969
|
+
|
1970
|
+
if router['type']['hasBgp']
|
1971
|
+
bgp_neighbor = (router['bgpNeighbors'] || []).find {|it| it['id'] == args[1].to_i}
|
1972
|
+
|
1973
|
+
if bgp_neighbor
|
1974
|
+
json_response = {'networkRouterBgpNeighbor' => bgp_neighbor}
|
1975
|
+
render_response(json_response, options, 'networkRouterBgpNeighbor') do
|
1976
|
+
print_h1 "Network Router BGP Neighbor Details"
|
1977
|
+
print cyan
|
1978
|
+
|
1979
|
+
description_cols = {
|
1980
|
+
"ID" => lambda {|it| it['id']}
|
1981
|
+
}
|
1982
|
+
|
1983
|
+
router['type']['bgpNeighborOptionTypes'].sort_by {|it| it['displayOrder']}.each do |option_type|
|
1984
|
+
description_cols[option_type['fieldLabel']] = lambda {|it| Morpheus::Cli::OptionTypes.get_option_value(it, option_type, true)}
|
1985
|
+
end
|
1986
|
+
print_description_list(description_cols, bgp_neighbor)
|
1987
|
+
end
|
1988
|
+
else
|
1989
|
+
print_red_alert "BGP Neighbors #{args[1]} not found for router #{router['name']}"
|
1990
|
+
end
|
1991
|
+
else
|
1992
|
+
print_red_alert "BGP Neighbors not supported for #{router['type']['name']}"
|
1993
|
+
end
|
1994
|
+
println reset
|
1995
|
+
end
|
1996
|
+
|
1997
|
+
def add_bgp_neighbor(args)
|
1998
|
+
options = {:options=>{}}
|
1999
|
+
params = {}
|
2000
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
2001
|
+
opts.banner = subcommand_usage("[router]")
|
2002
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
2003
|
+
opts.footer = "Create a network router BGP neighbor."
|
2004
|
+
end
|
2005
|
+
optparse.parse!(args)
|
2006
|
+
connect(options)
|
2007
|
+
if args.count < 1
|
2008
|
+
print_error Morpheus::Terminal.angry_prompt
|
2009
|
+
puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
|
2010
|
+
return 1
|
2011
|
+
end
|
2012
|
+
|
2013
|
+
router = find_router(args[0])
|
2014
|
+
|
2015
|
+
if router.nil?
|
2016
|
+
return 1
|
2017
|
+
end
|
2018
|
+
|
2019
|
+
if !router['type']['hasNat']
|
2020
|
+
print_red_alert "BGP not supported for #{router['type']['name']}"
|
2021
|
+
return 1
|
2022
|
+
end
|
2023
|
+
|
2024
|
+
if options[:payload]
|
2025
|
+
payload = options[:payload]
|
2026
|
+
else
|
2027
|
+
option_types = router['type']['bgpNeighborOptionTypes'].sort_by {|it| it['displayOrder']}
|
2028
|
+
|
2029
|
+
# prompt options
|
2030
|
+
option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'bgpNeighbor' => ''}}), @api_client, {'networkRouterId' => router['id']}, nil, true)
|
2031
|
+
payload = {'networkRouterBgpNeighbor' => params.deep_merge(option_result)}
|
2032
|
+
end
|
2033
|
+
|
2034
|
+
@network_routers_interface.setopts(options)
|
2035
|
+
if options[:dry_run]
|
2036
|
+
print_dry_run @network_routers_interface.dry.create_bgp_neighbor(router['id'], payload)
|
2037
|
+
return
|
2038
|
+
end
|
2039
|
+
|
2040
|
+
json_response = @network_routers_interface.create_bgp_neighbor(router['id'], payload)
|
2041
|
+
render_response(json_response, options, 'networkRouterBgpNeighbor') do
|
2042
|
+
print_green_success "\nAdded Network Router BGP neighbor #{json_response['id']}\n"
|
2043
|
+
_bgp_neighbors(router['id'], options)
|
2044
|
+
end
|
2045
|
+
end
|
2046
|
+
|
2047
|
+
def update_bgp_neighbor(args)
|
2048
|
+
options = {:options=>{}}
|
2049
|
+
params = {}
|
2050
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
2051
|
+
opts.banner = subcommand_usage("[router] [BGP neighbor]")
|
2052
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
2053
|
+
opts.footer = "Update a network router BGP neighbor.\n" +
|
2054
|
+
"[router] is required. This is the name or id of an existing network router.\n" +
|
2055
|
+
"[BGP neighbor] is required. This is the id of an existing network router BGP neighbor."
|
2056
|
+
end
|
2057
|
+
optparse.parse!(args)
|
2058
|
+
if args.count != 2
|
2059
|
+
raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
|
2060
|
+
end
|
2061
|
+
connect(options)
|
2062
|
+
|
2063
|
+
router = find_router(args[0])
|
2064
|
+
|
2065
|
+
if router.nil?
|
2066
|
+
return 1
|
2067
|
+
end
|
2068
|
+
|
2069
|
+
if !router['type']['hasBgp']
|
2070
|
+
print_red_alert "BGP not supported for #{router['type']['name']}"
|
2071
|
+
return 1
|
2072
|
+
end
|
2073
|
+
|
2074
|
+
bgp_neighbor = router['bgpNeighbors'] ? router['bgpNeighbors'].find {|it| it['id'] == args[1].to_i} : nil
|
2075
|
+
|
2076
|
+
if !bgp_neighbor
|
2077
|
+
print_red_alert "BGP neighbor #{args[1]} not found for router #{router['name']}"
|
2078
|
+
exit 1
|
2079
|
+
end
|
2080
|
+
|
2081
|
+
payload = parse_payload(options) || {'networkRouterBgpNeighbor' => params}
|
2082
|
+
payload['networkRouterBgpNeighbor'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options] && !payload['networkRouterBgpNeighbor'].nil?
|
2083
|
+
|
2084
|
+
if payload['networkRouterBgpNeighbor'].empty?
|
2085
|
+
option_types = router['type']['bgpNeighborOptionTypes'].sort_by {|it| it['displayOrder']}
|
2086
|
+
print_green_success "Nothing to update"
|
2087
|
+
println cyan
|
2088
|
+
print Morpheus::Cli::OptionTypes.display_option_types_help(
|
2089
|
+
option_types,
|
2090
|
+
{:include_context => true, :context_map => {'bgpNeighbor' => ''}, :color => cyan, :title => "Available BGP Neighbor Options"}
|
2091
|
+
)
|
2092
|
+
exit 1
|
2093
|
+
end
|
2094
|
+
|
2095
|
+
@network_routers_interface.setopts(options)
|
2096
|
+
if options[:dry_run]
|
2097
|
+
print_dry_run @network_routers_interface.dry.update_bgp_neighbor(router['id'], bgp_neighbor['id'], payload)
|
2098
|
+
return
|
2099
|
+
end
|
2100
|
+
|
2101
|
+
json_response = @network_routers_interface.update_bgp_neighbor(router['id'], bgp_neighbor['id'], payload)
|
2102
|
+
render_response(json_response, options, 'networkRouterBgpNeighbor') do
|
2103
|
+
print_green_success "\nUpdated Network Router BGP Neighbor #{bgp_neighbor['id']}\n"
|
2104
|
+
_bgp_neighbors(router['id'], options)
|
2105
|
+
end
|
2106
|
+
end
|
2107
|
+
|
2108
|
+
def remove_bgp_neighbor(args)
|
2109
|
+
options = {}
|
2110
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
2111
|
+
opts.banner = subcommand_usage("[router] [BGP neighbor]")
|
2112
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
|
2113
|
+
opts.footer = "Delete a network router BGP neighbor.\n" +
|
2114
|
+
"[router] is required. This is the name or id of an existing network router."
|
2115
|
+
"[BGP neighbor] is required. This is the id of an existing network router BGP neighbor."
|
2116
|
+
end
|
2117
|
+
optparse.parse!(args)
|
2118
|
+
if args.count != 2
|
2119
|
+
raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
|
2120
|
+
end
|
2121
|
+
connect(options)
|
2122
|
+
|
2123
|
+
router = find_router(args[0])
|
2124
|
+
return if !router
|
2125
|
+
|
2126
|
+
if !router['type']['hasBgp']
|
2127
|
+
print_red_alert "BGP not supported for #{router['type']['name']}"
|
2128
|
+
return 1
|
2129
|
+
end
|
2130
|
+
|
2131
|
+
bgp_neighbor = router['bgpNeighbors'] ? router['bgpNeighbors'].find {|it| it['id'] == args[1].to_i} : nil
|
2132
|
+
|
2133
|
+
if !bgp_neighbor
|
2134
|
+
print_red_alert "BGP neighbor #{args[1]} not found for router #{router['name']}"
|
2135
|
+
exit 1
|
2136
|
+
end
|
2137
|
+
|
2138
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the BGP neighbor '#{bgp_neighbor['id']}' from router '#{router['name']}'?", options)
|
2139
|
+
return 9, "aborted command"
|
2140
|
+
end
|
2141
|
+
@network_routers_interface.setopts(options)
|
2142
|
+
if options[:dry_run]
|
2143
|
+
print_dry_run @network_routers_interface.dry.destroy_bgp_neighbor(router['id'], bgp_neighbor['id'])
|
2144
|
+
return
|
2145
|
+
end
|
2146
|
+
json_response = @network_routers_interface.destroy_bgp_neighbor(router['id'], bgp_neighbor['id'])
|
2147
|
+
render_response(json_response, options, 'networkRouterBgpNeighbor') do
|
2148
|
+
print_green_success "\nDeleted Network Router BGP Neighbor #{bgp_neighbor['id']}\n"
|
2149
|
+
_bgp_neighbors(router['id'], options)
|
2150
|
+
end
|
2151
|
+
end
|
2152
|
+
|
1890
2153
|
def types(args)
|
1891
2154
|
options = {}
|
1892
2155
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
@@ -1989,7 +2252,7 @@ class Morpheus::Cli::NetworkRoutersCommand
|
|
1989
2252
|
}
|
1990
2253
|
print_description_list(description_cols, router_type)
|
1991
2254
|
|
1992
|
-
{'optionTypes' => 'Router', 'ruleOptionTypes' => 'Firewall Rule', 'ruleGroupOptionTypes' => 'Firewall Rule Group', 'natOptionTypes' => 'NAT'}.each_pair do |field, title|
|
2255
|
+
{'optionTypes' => 'Router', 'ruleOptionTypes' => 'Firewall Rule', 'ruleGroupOptionTypes' => 'Firewall Rule Group', 'natOptionTypes' => 'NAT', 'bgpNeighborOptionTypes' => 'BGP Neighbor'}.each_pair do |field, title|
|
1993
2256
|
if !router_type[field].nil? && router_type[field].count > 0
|
1994
2257
|
println cyan
|
1995
2258
|
print Morpheus::Cli::OptionTypes.display_option_types_help(
|
@@ -2187,6 +2450,27 @@ class Morpheus::Cli::NetworkRoutersCommand
|
|
2187
2450
|
end
|
2188
2451
|
end
|
2189
2452
|
|
2453
|
+
def print_bgp_neighbors(router)
|
2454
|
+
if router['type']['hasBgp']
|
2455
|
+
if router['bgpNeighbors'].count > 0
|
2456
|
+
rows = router['bgpNeighbors'].sort_by {|it| it['id']}.collect do |it|
|
2457
|
+
{
|
2458
|
+
id: it['id'],
|
2459
|
+
ip_address: it['ipAddress'],
|
2460
|
+
bfd_enabled: it['bfdEnabled'],
|
2461
|
+
remote_as: it['remoteAs'],
|
2462
|
+
route_filtering_out: it['routeFilteringOut'],
|
2463
|
+
route_filtering_in: it['routeFilteringIn'],
|
2464
|
+
allow_as_in: it['allowAsIn']
|
2465
|
+
}
|
2466
|
+
end
|
2467
|
+
puts as_pretty_table(rows, [:id, :ip_address, :bfd_enabled, :remote_as, :route_filtering_out, :route_filtering_in, :allow_as_in])
|
2468
|
+
else
|
2469
|
+
println "No BGP Neighbors\n"
|
2470
|
+
end
|
2471
|
+
end
|
2472
|
+
end
|
2473
|
+
|
2190
2474
|
def format_router_status(router, return_color = cyan)
|
2191
2475
|
status = router['status']
|
2192
2476
|
color = white
|