morpheus-cli 5.3.3 → 5.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +12 -0
  4. data/lib/morpheus/api/clouds_interface.rb +4 -11
  5. data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
  6. data/lib/morpheus/api/load_balancer_profiles_interface.rb +10 -0
  7. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +4 -4
  8. data/lib/morpheus/api/network_routers_interface.rb +21 -0
  9. data/lib/morpheus/api/network_servers_interface.rb +42 -0
  10. data/lib/morpheus/api/rest_interface.rb +2 -1
  11. data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
  12. data/lib/morpheus/cli/cli_command.rb +2 -1
  13. data/lib/morpheus/cli/cloud_resource_pools_command.rb +1 -1
  14. data/lib/morpheus/cli/clouds.rb +22 -40
  15. data/lib/morpheus/cli/hosts.rb +0 -1
  16. data/lib/morpheus/cli/instances.rb +111 -7
  17. data/lib/morpheus/cli/invoices_command.rb +42 -38
  18. data/lib/morpheus/cli/library_option_lists_command.rb +3 -3
  19. data/lib/morpheus/cli/load_balancer_pools.rb +111 -0
  20. data/lib/morpheus/cli/load_balancer_virtual_servers.rb +136 -0
  21. data/lib/morpheus/cli/load_balancers.rb +0 -155
  22. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +2 -2
  23. data/lib/morpheus/cli/mixins/provisioning_helper.rb +32 -11
  24. data/lib/morpheus/cli/mixins/rest_command.rb +53 -37
  25. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +488 -0
  26. data/lib/morpheus/cli/network_routers_command.rb +291 -7
  27. data/lib/morpheus/cli/network_scopes_command.rb +442 -0
  28. data/lib/morpheus/cli/networks_command.rb +2 -2
  29. data/lib/morpheus/cli/option_types.rb +20 -0
  30. data/lib/morpheus/cli/subnets_command.rb +7 -2
  31. data/lib/morpheus/cli/tasks.rb +25 -2
  32. data/lib/morpheus/cli/version.rb +1 -1
  33. data/lib/morpheus/cli/virtual_images.rb +2 -0
  34. data/lib/morpheus/cli.rb +9 -1
  35. 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] [rule]")
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
- "[router] is required. This is the name or id of an existing network router."
1524
- "[route] is required. This is the name or id of an existing network router route."
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] [rule]")
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
- "[rule] is required. This is the name or id of a firewall rule.\n"
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