rockette 0.0.1 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../text_helper"
4
+ require_relative "../commands/export"
5
+
6
+ module Rockette
7
+ # Export and download APEX application
8
+ class Exporter
9
+ include TextHelper
10
+
11
+ def initialize
12
+ @pastel = Pastel.new
13
+ @prompt = TTY::Prompt.new
14
+ @spinner = TTY::Spinner.new
15
+ end
16
+
17
+ def launch!
18
+ @conf = Psych.load(File.read(CONF))
19
+ puts padder("Choose an application to download.")
20
+ puts
21
+
22
+ # input/action loop
23
+ loop do
24
+ enviros = Rockette::Viewer.new.environments
25
+ list = list_builder(enviros)
26
+ action = @prompt.select("Which environment is the app found?", list)
27
+ break if action == list.length
28
+
29
+ apps_url = enviros[action - 1]["deployment_api"]
30
+ choose_app(apps_url)
31
+ end
32
+ end
33
+
34
+ def do_export(app_id, apps_url)
35
+ response = @prompt.yes?("Would you like to enter a filename for the export?")
36
+ if response == true
37
+ file = @prompt.ask("Please enter your desired filename:")
38
+ options = Thor::CoreExt::HashWithIndifferentAccess.new "app_id" => app_id, "url" => apps_url, "file" => file,
39
+ "force" => true
40
+ else
41
+ puts padder("Saving under default file name: f#{app_id}.sql")
42
+ options = Thor::CoreExt::HashWithIndifferentAccess.new "app_id" => app_id, "url" => apps_url, "force" => true
43
+ end
44
+ Rockette::Commands::Export.new(options).execute
45
+ puts
46
+ end
47
+
48
+ protected
49
+
50
+ def choose_app(apps_url)
51
+ loop do
52
+ apps = Rockette::Viewer.new.applications(apps_url)
53
+ list = list_builder(apps)
54
+ action = @prompt.slider("Download application => ", list, default: 1)
55
+ break if action == list.length
56
+
57
+ app_id = apps[action - 1]["application_id"]
58
+ do_export(app_id, apps_url)
59
+ end
60
+ end
61
+
62
+ def list_builder(array)
63
+ names = [] # Start building selection list
64
+ if array[0].key?("name")
65
+ array.each { |n| names << n["name"] }
66
+ else
67
+ array.each { |n| names << "#{n["application_name"]} App ID: #{n["application_id"]}" }
68
+ end
69
+ names << "Go Back"
70
+ names.map.with_index { |n, x| [n, x + 1] }.to_h
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../text_helper"
4
+
5
+ module Rockette
6
+ # View resources
7
+ class Viewer
8
+ include TextHelper
9
+
10
+ def initialize
11
+ @conf = Psych.load(File.read(CONF))
12
+ @pastel = Pastel.new
13
+ @prompt = TTY::Prompt.new
14
+ @spinner = TTY::Spinner.new # ("[:spinner] Loading APEX environments ...", format: pulse_2)
15
+ @view_actions = { "🏔 APEX Environments" => 1, "🎭 Registered Applications" => 2,
16
+ "🌎 Applications by Environment" => 3, "⬅️ Go Back" => 4 }
17
+ end
18
+
19
+ def launch!
20
+ puts padder("You can view environments or registered applications")
21
+ puts
22
+
23
+ # input/action loop
24
+ loop do
25
+ action = @prompt.select("Which would you like to see?", @view_actions)
26
+ break if action == 4
27
+
28
+ do_action(action)
29
+ end
30
+ end
31
+
32
+ def do_action(action)
33
+ case action
34
+ when 1
35
+ puts
36
+ environments unless @table_env
37
+ spinner(0.5)
38
+ puts @table_env.render(:unicode, resize: true, border: { style: :yellow })
39
+ puts
40
+ when 2
41
+ puts
42
+ registered unless @table_reg
43
+ puts @table_reg.render(:unicode, resize: true, border: { style: :yellow })
44
+ puts
45
+ when 3
46
+ puts
47
+ puts "This can take a while...hang tight!"
48
+ puts
49
+ all_apps unless @table_all_apps
50
+ puts @table_all_apps.render(:unicode, resize: true, border: { style: :yellow })
51
+ puts
52
+ else
53
+ puts "\nI don't understand that command.\n\n"
54
+ end
55
+ end
56
+
57
+ def ape_e_i(uri)
58
+ response = Rester.new(url: uri).rest_try
59
+ bail unless response
60
+ abort padder("#{uri} didn't work. Received: #{response.code}") unless response.code == 200
61
+ response
62
+ end
63
+
64
+ def applications(url)
65
+ uri = "#{url}deploy/apps"
66
+ response = ape_e_i(uri)
67
+ JSON.parse(response.body)["items"]
68
+ end
69
+
70
+ def environments
71
+ uri = "#{@conf["rockette"]["controller_url"]}deploy/environments/"
72
+ response = ape_e_i(uri)
73
+ @table_env = TTY::Table.new(header: ["Environment Name", "API", "Domain", "Owner", "Workspace"])
74
+ items = JSON.parse(response.body)["items"]
75
+ items.each { |h| @table_env << [h["name"], h["deployment_api"], h["domain"], h["owner"], h["workspace"]] }
76
+ end
77
+
78
+ def registered
79
+ uri = "#{@conf["rockette"]["controller_url"]}deploy/registered_apps/"
80
+ response = ape_e_i(uri)
81
+ @table_reg = TTY::Table.new(header: ["Registered Name", "Source App ID", "Source URI", "Target App ID",
82
+ "Target URI"])
83
+ JSON.parse(response.body)["items"].each do |h|
84
+ @table_reg << [h["registered_name"], h["src_app_id"], h["src_url"], h["tgt_app_id"], h["tgt_url"]]
85
+ end
86
+ end
87
+
88
+ def all_apps
89
+ environments unless @table_env
90
+ @table_all_apps = TTY::Table.new(header: ["Environment Name", "Application Name", "Application ID"])
91
+ @table_env.each do |env|
92
+ next if env[0] == "Environment Name"
93
+
94
+ apps = applications(env[1])
95
+ apps.each do |app|
96
+ @table_all_apps << [env[0], app["application_name"], app["application_id"]]
97
+ end
98
+ end
99
+ end
100
+
101
+ def spinner(dur=1)
102
+ @spinner.auto_spin
103
+ sleep(dur)
104
+ @spinner.stop
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "controller/configurator"
4
+ require_relative "controller/deployer"
5
+ require_relative "controller/exporter"
6
+ require_relative "controller/viewer"
7
+ require_relative "text_helper"
8
+
9
+ module Rockette
10
+ MAIN_ACTIONS = { "🔭 View Resources" => 1, "🚀 Deploy" => 2, "📥 Export" => 3,
11
+ "🛠 Configure" => 4, "❌ Quit" => 5 }.freeze
12
+ # Manage Rockette in interactive mode
13
+ class Controller
14
+ def initialize
15
+ @conf = Psych.load(File.read(CONF))
16
+ @pastel = Pastel.new
17
+ @prompt = TTY::Prompt.new
18
+ end
19
+
20
+ def launch!
21
+ introduction
22
+
23
+ if @conf["rockette"]["check_for_url"] && @conf["rockette"]["controller_url"].length < 10
24
+ configurer = Rockette::Configurator.new
25
+ configurer.first_run
26
+ end
27
+
28
+ # input/action loop
29
+ loop do
30
+ action = actions
31
+ break if action == 5
32
+
33
+ do_action(action)
34
+ end
35
+ conclusion
36
+ end
37
+
38
+ private
39
+
40
+ def introduction
41
+ font = TTY::Font.new(:starwars)
42
+ puts "-" * 85
43
+ puts
44
+ puts @pastel.yellow(font.write("Rockette"))
45
+ puts
46
+ puts "-" * 85
47
+ puts "Version: " + VERSION
48
+ puts "-" * 14
49
+ puts
50
+ puts "Rockette helps export and deploy APEX applications."
51
+ puts
52
+ end
53
+
54
+ def conclusion
55
+ puts
56
+ puts "-" * 85
57
+ puts @pastel.yellow("Have a good one!".upcase.center(85))
58
+ puts "-" * 85
59
+ puts
60
+ end
61
+
62
+ def actions
63
+ @prompt.select("What would you like to do?", MAIN_ACTIONS)
64
+ end
65
+
66
+ def do_action(action)
67
+ case action
68
+ when 1
69
+ viewer = Rockette::Viewer.new
70
+ viewer.launch!
71
+ when 2
72
+ deployer = Rockette::Deployer.new
73
+ deployer.launch!
74
+ when 3
75
+ exporter = Rockette::Exporter.new
76
+ exporter.launch!
77
+ when 4
78
+ configurer = Rockette::Configurator.new
79
+ configurer.launch!
80
+ else
81
+ puts "\nI don't understand that command.\n\n"
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rockette
4
+ # configurable rest-client calls with error handling and auto retries
5
+ class Rester
6
+ VERBS = {
7
+ "delete" => :Delete,
8
+ "get" => :Get,
9
+ "post" => :Post,
10
+ "put" => :Put
11
+ }.freeze
12
+
13
+ def initialize(headers: {}, meth: "Get", params: {}, url: "https://array/", config: {})
14
+ @headers = headers
15
+ @meth = meth
16
+ @params = params
17
+ @url = url
18
+ @config = config
19
+ @config["timeout"] = @config["timeout"] ||= 30
20
+ end
21
+
22
+ def make_call
23
+ response = RestClient::Request.execute(headers: @headers,
24
+ method: VERBS[@meth.downcase], payload: @params,
25
+ timeout: @config["timeout"], url: @url, verify_ssl: false)
26
+ rescue SocketError, IOError => e
27
+ puts "#{e.class}: #{e.message}"
28
+ nil
29
+ rescue StandardError => e
30
+ e.response
31
+ else
32
+ response
33
+ end
34
+
35
+ def cookie
36
+ if @url =~ %r{auth/session}
37
+ response = make_call
38
+ raise "There was an issue getting a cookie!" unless response.code == 200
39
+
40
+ (response.cookies.map { |key, val| "#{key}=#{val}" })[0]
41
+ else
42
+ error_text("cookie", @url.to_s, "auth/session")
43
+ end
44
+ end
45
+
46
+ # use rest-client with retry
47
+ def rest_try(tries = 3)
48
+ tries.times do |i|
49
+ response = make_call
50
+ unless response.nil?
51
+ break response if (200..299).include? response.code
52
+ break response if i > 1
53
+ end
54
+ puts "Failed #{@meth} on #{@url}, retry...#{i + 1}"
55
+ sleep 3 unless i > 1
56
+ return nil if i > 1 # Handles socket errors, etc. where there is no response.
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def error_text(method_name, url, wanted)
63
+ {
64
+ "response" =>
65
+ "ERROR: Wrong url for the #{method_name} method.\n"\
66
+ "Sent: #{url}\n"\
67
+ "Expected: \"#{wanted}\" as part of the url.",
68
+ "status" => 400
69
+ }
70
+ end
71
+
72
+ def responder(response)
73
+ {
74
+ "response" => JSON.parse(response.body),
75
+ "status" => response.code.to_i
76
+ }
77
+ end
78
+ end
79
+ end
@@ -3,8 +3,9 @@
3
3
  # Add common methods to Rockette module
4
4
  module TextHelper
5
5
  def bail
6
- puts "Bailing, unable to check for application. Can you access the url from here?"
6
+ puts "Bailing, a socket (network) or IO error occurred. Can you access the url from here?"
7
7
  puts "Double check the url and make sure you have a network connection to the target."
8
+ puts
8
9
  exit
9
10
  end
10
11
 
@@ -12,6 +13,18 @@ module TextHelper
12
13
  input unless input.nil?
13
14
  end
14
15
 
16
+ def file_not_found
17
+ puts "File not found. Double check file name and place in ~/.rockette/exports, /usr/app, or /usr/local/app"
18
+ puts
19
+ exit
20
+ end
21
+
22
+ def no_rockette_dir
23
+ puts "Unable to locate a suitable place for the .rockette directory."
24
+ puts "Please double check your home directory..."
25
+ exit
26
+ end
27
+
15
28
  def padder(str)
16
29
  "\n#{str}\n"
17
30
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rockette
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.5"
5
5
  end
data/lib/rockette.rb CHANGED
@@ -1,91 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "erb"
4
- require "json"
5
- require "psych"
6
- require "rest-client"
7
- require "thor"
8
- require_relative "rockette/cli"
9
- require_relative "rockette/text_helper"
10
- require_relative "rockette/version"
3
+ require_relative "requirements"
4
+
5
+ # Set paths
6
+ APP_PATH = if File.exist?(File.join("/", "usr", "app"))
7
+ File.join("/", "usr", "app", ".rockette")
8
+ elsif File.exist?(Dir.home)
9
+ File.join(Dir.home, ".rockette")
10
+ else
11
+ no_rockette_dir
12
+ end
13
+ lib_path = File.expand_path("../lib", __dir__)
14
+ tem_path = File.expand_path("../templates", __dir__)
15
+ $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
16
+
17
+ # Create directories and config file if needed
18
+ Dir.mkdir(APP_PATH) unless File.exist?(APP_PATH)
19
+ unless File.exist?(File.join(APP_PATH, "config.yml"))
20
+ template = File.read(File.join(tem_path, "config.yml.erb"))
21
+ data = ERB.new(template).result(binding)
22
+ File.write(File.join(APP_PATH, "config.yml"), data)
23
+ end
24
+ Dir.mkdir(File.join(APP_PATH, "exports")) unless File.exist?(File.join(APP_PATH, "exports"))
25
+
26
+ # Set config and export directory paths
27
+ CONF = File.join(APP_PATH, "config.yml")
28
+ ENV["THOR_SILENCE_DEPRECATION"] = "true"
29
+ EXPORT_DIR = File.join(APP_PATH, "exports")
11
30
 
12
31
  # APEX deployment
13
32
  module Rockette
14
33
  class Error < StandardError; end
15
-
16
- # rest-client calls with error handling and auto retries
17
- class Rester
18
- VERBS = {
19
- "delete" => :Delete,
20
- "get" => :Get,
21
- "post" => :Post,
22
- "put" => :Put
23
- }.freeze
24
-
25
- def initialize(headers: {}, meth: "Get", params: {}, url: "https://array/", config: {})
26
- @headers = headers
27
- @meth = meth
28
- @params = params
29
- @url = url
30
- @config = config
31
- @config["timeout"] = @config["timeout"] ||= 30
32
- end
33
-
34
- def make_call
35
- response = RestClient::Request.execute(headers: @headers,
36
- method: VERBS[@meth.downcase], payload: @params,
37
- timeout: @config["timeout"], url: @url, verify_ssl: false)
38
- rescue SocketError => e
39
- puts "#{e.class}: #{e.message}"
40
- nil
41
- rescue StandardError => e
42
- e.response
43
- else
44
- response
45
- end
46
-
47
- def cookie
48
- if @url =~ %r{auth/session}
49
- response = make_call
50
- raise "There was an issue getting a cookie!" unless response.code == 200
51
-
52
- (response.cookies.map { |key, val| "#{key}=#{val}" })[0]
53
- else
54
- error_text("cookie", @url.to_s, "auth/session")
55
- end
56
- end
57
-
58
- # use rest-client with retry
59
- def rest_try
60
- 3.times do |i|
61
- response = make_call
62
- unless response.nil?
63
- break response if (200..299).include? response.code
64
- break response if i > 1
65
- end
66
- puts "Failed #{@meth} on #{@url}, retry...#{i + 1}"
67
- sleep 3 unless i > 1
68
- return nil if i > 1 # Handles socket errors, etc. where there is no response.
69
- end
70
- end
71
-
72
- private
73
-
74
- def error_text(method_name, url, wanted)
75
- {
76
- "response" =>
77
- "ERROR: Wrong url for the #{method_name} method.\n"\
78
- "Sent: #{url}\n"\
79
- "Expected: \"#{wanted}\" as part of the url.",
80
- "status" => 400
81
- }
82
- end
83
-
84
- def responder(response)
85
- {
86
- "response" => JSON.parse(response.body),
87
- "status" => response.code.to_i
88
- }
89
- end
90
- end
34
+ # Code in lib/rockette
91
35
  end
data/rockette.gemspec CHANGED
@@ -32,10 +32,15 @@ Gem::Specification.new do |spec|
32
32
  # Dev dependencies
33
33
  spec.add_development_dependency "pry", "~> 0.0"
34
34
 
35
- # Uncomment to register a new dependency of your gem
35
+ # Dependencies
36
+ spec.add_dependency "oci", "~> 2.0"
37
+ spec.add_dependency "pastel", "~> 0.0"
36
38
  spec.add_dependency "rest-client", "~> 2.0"
37
39
  spec.add_dependency "thor", "~> 1.0"
38
-
39
- # For more information and examples about making a new gem, checkout our
40
- # guide at: https://bundler.io/guides/creating_gem.html
40
+ spec.add_dependency "tty-config", "~> 0.0"
41
+ spec.add_dependency "tty-editor", "~> 0.0"
42
+ spec.add_dependency "tty-font", "~> 0.0"
43
+ spec.add_dependency "tty-prompt", "~> 0.0"
44
+ spec.add_dependency "tty-spinner", "~> 0.0"
45
+ spec.add_dependency "tty-table", "~> 0.0"
41
46
  end
@@ -1,17 +1,8 @@
1
1
  ---
2
- push_hdrs:
3
- Content-Type: application/json
4
- created_by: dcs_automation
5
- message_date: ''
6
- msg_from_addr: ''
7
- msg_from_name: ''
8
- file_charset: UTF-8
9
- file_mimetype: text/plain
10
- file_name: ''
11
- file_type: sql
12
- tags: ''
13
- target_use: push_deployment
14
- deploy_body:
15
- app_id_src: ''
16
- app_id_tgt: ''
17
- blob_url: https://local.data_loader
2
+ token_body:
3
+ grant_type: client_credentials
4
+ token_hdrs:
5
+ Content-Type: application/x-www-form-urlencoded
6
+ rockette:
7
+ check_for_url: true
8
+ controller_url: ''