rockette 0.0.2 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +15 -1
- data/Gemfile.lock +58 -14
- data/exe/rockette +0 -17
- data/lib/requirements.rb +21 -0
- data/lib/rockette/cli.rb +24 -7
- data/lib/rockette/commands/deploy.rb +45 -22
- data/lib/rockette/commands/export.rb +18 -18
- data/lib/rockette/commands/interactive.rb +24 -0
- data/lib/rockette/controller/configurator.rb +98 -0
- data/lib/rockette/controller/deployer.rb +108 -0
- data/lib/rockette/controller/exporter.rb +74 -0
- data/lib/rockette/controller/viewer.rb +154 -0
- data/lib/rockette/controller.rb +85 -0
- data/lib/rockette/rester.rb +79 -0
- data/lib/rockette/text_helper.rb +6 -0
- data/lib/rockette/version.rb +1 -1
- data/lib/rockette.rb +28 -84
- data/rockette.gemspec +9 -4
- data/templates/config.yml.erb +8 -16
- metadata +123 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26e8d73d2c9b1c9a543b41dfd95dda73efea46e5bb14d444a5f50ada2af968ce
|
4
|
+
data.tar.gz: 44b7d193c2ad1ff6dcb9efad3ab7b5a70c87ba8942fb919aec5fa2302c4282b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0124ec971be8e538d810582967a512dc26efbaa2ed9e6e9f61fd9f1a954b40b2d3e6625e0b91aa813eac9902350cb3df2ce9f8c1f018edcc9aabdfaa87c73e43
|
7
|
+
data.tar.gz: aabc39c4210d4ec7dc7ca56cede861c433349fe395088657eba03744c3ced88ca91d7227ddba1488a48d238e87d1d92c05bda232a0d0907a057e7b90d61a193e
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -16,4 +16,18 @@
|
|
16
16
|
|
17
17
|
- Add copy switch to deploy command
|
18
18
|
- Use file name passed via -f switch
|
19
|
-
- Try to find export file and let caller know if file not found
|
19
|
+
- Try to find export file and let caller know if file not found
|
20
|
+
|
21
|
+
## [0.0.3] - 2021-03-29
|
22
|
+
|
23
|
+
- Improved handling of copy and file switches
|
24
|
+
- Check /usr/app for Docker
|
25
|
+
- Add interactive mode
|
26
|
+
- Add configuration option to interactive mode
|
27
|
+
- Add resource viewer mode to interactive
|
28
|
+
- Add exporter option to interactive
|
29
|
+
- Add deployer mode to interactive
|
30
|
+
|
31
|
+
## [0.0.4] - 2021-03-29
|
32
|
+
|
33
|
+
- Bug fix for APP_DIR
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rockette (0.0.
|
4
|
+
rockette (0.0.5)
|
5
|
+
oci (~> 2.0)
|
6
|
+
pastel (~> 0.0)
|
5
7
|
rest-client (~> 2.0)
|
6
8
|
thor (~> 1.0)
|
9
|
+
tty-config (~> 0.0)
|
10
|
+
tty-editor (~> 0.0)
|
11
|
+
tty-font (~> 0.0)
|
12
|
+
tty-prompt (~> 0.0)
|
13
|
+
tty-spinner (~> 0.0)
|
14
|
+
tty-table (~> 0.0)
|
7
15
|
|
8
16
|
GEM
|
9
17
|
remote: https://rubygems.org/
|
@@ -13,46 +21,82 @@ GEM
|
|
13
21
|
domain_name (0.5.20190701)
|
14
22
|
unf (>= 0.0.5, < 1.0.0)
|
15
23
|
http-accept (1.7.0)
|
16
|
-
http-cookie (1.0.
|
24
|
+
http-cookie (1.0.4)
|
17
25
|
domain_name (~> 0.5)
|
26
|
+
inifile (3.0.0)
|
27
|
+
json (2.5.1)
|
28
|
+
jwt (2.2.3)
|
18
29
|
method_source (1.0.0)
|
19
30
|
mime-types (3.3.1)
|
20
31
|
mime-types-data (~> 3.2015)
|
21
|
-
mime-types-data (3.2021.
|
32
|
+
mime-types-data (3.2021.0901)
|
22
33
|
minitest (5.14.4)
|
23
34
|
netrc (0.11.0)
|
24
|
-
|
25
|
-
|
35
|
+
oci (2.15.0)
|
36
|
+
inifile (~> 3.0, >= 3.0.0)
|
37
|
+
json (>= 1.4.6, < 3.0.0)
|
38
|
+
jwt (~> 2.1)
|
39
|
+
parallel (1.21.0)
|
40
|
+
parser (3.0.2.0)
|
26
41
|
ast (~> 2.4.1)
|
27
|
-
|
42
|
+
pastel (0.8.0)
|
43
|
+
tty-color (~> 0.5)
|
44
|
+
pry (0.14.1)
|
28
45
|
coderay (~> 1.1)
|
29
46
|
method_source (~> 1.0)
|
30
47
|
rainbow (3.0.0)
|
31
|
-
rake (13.0.
|
48
|
+
rake (13.0.6)
|
32
49
|
regexp_parser (2.1.1)
|
33
50
|
rest-client (2.1.0)
|
34
51
|
http-accept (>= 1.7.0, < 2.0)
|
35
52
|
http-cookie (>= 1.0.2, < 2.0)
|
36
53
|
mime-types (>= 1.16, < 4.0)
|
37
54
|
netrc (~> 0.8)
|
38
|
-
rexml (3.2.
|
39
|
-
rubocop (1.
|
55
|
+
rexml (3.2.5)
|
56
|
+
rubocop (1.21.0)
|
40
57
|
parallel (~> 1.10)
|
41
58
|
parser (>= 3.0.0.0)
|
42
59
|
rainbow (>= 2.2.2, < 4.0)
|
43
60
|
regexp_parser (>= 1.8, < 3.0)
|
44
61
|
rexml
|
45
|
-
rubocop-ast (>= 1.
|
62
|
+
rubocop-ast (>= 1.9.1, < 2.0)
|
46
63
|
ruby-progressbar (~> 1.7)
|
47
64
|
unicode-display_width (>= 1.4.0, < 3.0)
|
48
|
-
rubocop-ast (1.
|
49
|
-
parser (>=
|
65
|
+
rubocop-ast (1.11.0)
|
66
|
+
parser (>= 3.0.1.1)
|
50
67
|
ruby-progressbar (1.11.0)
|
68
|
+
strings (0.2.1)
|
69
|
+
strings-ansi (~> 0.2)
|
70
|
+
unicode-display_width (>= 1.5, < 3.0)
|
71
|
+
unicode_utils (~> 1.4)
|
72
|
+
strings-ansi (0.2.0)
|
51
73
|
thor (1.1.0)
|
74
|
+
tty-color (0.6.0)
|
75
|
+
tty-config (0.5.0)
|
76
|
+
tty-cursor (0.7.1)
|
77
|
+
tty-editor (0.7.0)
|
78
|
+
tty-prompt (~> 0.22)
|
79
|
+
tty-font (0.5.0)
|
80
|
+
tty-prompt (0.23.1)
|
81
|
+
pastel (~> 0.8)
|
82
|
+
tty-reader (~> 0.8)
|
83
|
+
tty-reader (0.9.0)
|
84
|
+
tty-cursor (~> 0.7)
|
85
|
+
tty-screen (~> 0.8)
|
86
|
+
wisper (~> 2.0)
|
87
|
+
tty-screen (0.8.1)
|
88
|
+
tty-spinner (0.9.3)
|
89
|
+
tty-cursor (~> 0.7)
|
90
|
+
tty-table (0.12.0)
|
91
|
+
pastel (~> 0.8)
|
92
|
+
strings (~> 0.2.0)
|
93
|
+
tty-screen (~> 0.8)
|
52
94
|
unf (0.1.4)
|
53
95
|
unf_ext
|
54
|
-
unf_ext (0.0.
|
55
|
-
unicode-display_width (2.
|
96
|
+
unf_ext (0.0.8)
|
97
|
+
unicode-display_width (2.1.0)
|
98
|
+
unicode_utils (1.4.0)
|
99
|
+
wisper (2.0.1)
|
56
100
|
|
57
101
|
PLATFORMS
|
58
102
|
ruby
|
data/exe/rockette
CHANGED
@@ -3,23 +3,6 @@
|
|
3
3
|
|
4
4
|
require "rockette"
|
5
5
|
|
6
|
-
app_path = File.join(Dir.home, ".rockette")
|
7
|
-
lib_path = File.expand_path("../lib", __dir__)
|
8
|
-
tem_path = File.expand_path("../templates", __dir__)
|
9
|
-
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
10
|
-
|
11
|
-
Dir.mkdir(app_path) unless File.exist?(app_path)
|
12
|
-
unless File.exist?(File.join(app_path, "config.yml"))
|
13
|
-
template = File.read(File.join(tem_path, "config.yml.erb"))
|
14
|
-
data = ERB.new(template).result(binding)
|
15
|
-
File.write(File.join(app_path, "config.yml"), data)
|
16
|
-
end
|
17
|
-
Dir.mkdir(File.join(app_path, "exports")) unless File.exist?(File.join(app_path, "exports"))
|
18
|
-
|
19
|
-
CONF = Psych.load(File.read(File.join(app_path, "config.yml")))
|
20
|
-
ENV["THOR_SILENCE_DEPRECATION"] = "true"
|
21
|
-
EXPORT_DIR = File.join(app_path, "exports")
|
22
|
-
|
23
6
|
Signal.trap("INT") do
|
24
7
|
warn("\n#{caller.join("\n")}: interrupted")
|
25
8
|
exit(1)
|
data/lib/requirements.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
require "erb"
|
5
|
+
require "json"
|
6
|
+
require "oci"
|
7
|
+
require "pastel"
|
8
|
+
require "psych"
|
9
|
+
require "rest-client"
|
10
|
+
require "thor"
|
11
|
+
require "tty-config"
|
12
|
+
require "tty-editor"
|
13
|
+
require "tty-font"
|
14
|
+
require "tty-prompt"
|
15
|
+
require "tty-spinner"
|
16
|
+
require "tty-table"
|
17
|
+
require_relative "rockette/cli"
|
18
|
+
require_relative "rockette/controller"
|
19
|
+
require_relative "rockette/rester"
|
20
|
+
require_relative "rockette/text_helper"
|
21
|
+
require_relative "rockette/version"
|
data/lib/rockette/cli.rb
CHANGED
@@ -18,14 +18,14 @@ module Rockette
|
|
18
18
|
desc "deploy", "Deploy chosen export file to target APEX instance"
|
19
19
|
method_option :help, aliases: "-h", type: :boolean,
|
20
20
|
desc: "Display usage information"
|
21
|
-
option :app_id, aliases: "-a",
|
22
|
-
desc: "
|
21
|
+
option :app_id, aliases: "-a", default: "0",
|
22
|
+
desc: "Update this App ID with export set by '-f' Omitting '-a' copies export to target"
|
23
23
|
option :file, aliases: "-f", required: true,
|
24
|
-
desc: "Provide an APEX application export file (
|
24
|
+
desc: "Provide an APEX application export file (sql)"
|
25
25
|
option :url, aliases: "-u", required: true,
|
26
26
|
desc: "Provide a valid APEX deployment url"
|
27
|
-
option :
|
28
|
-
desc: "Use this flag if you are
|
27
|
+
option :secret, aliases: "-s", required: false,
|
28
|
+
desc: "Use this flag if you are using managed secrets"
|
29
29
|
def deploy(*)
|
30
30
|
if options[:help]
|
31
31
|
invoke :help, ["deploy"]
|
@@ -42,6 +42,9 @@ module Rockette
|
|
42
42
|
desc: "Provide an APEX application ID"
|
43
43
|
option :url, aliases: "-u", required: true,
|
44
44
|
desc: "Provide a valid url"
|
45
|
+
option :file, aliases: "-f", required: false,
|
46
|
+
desc: "Save export with this file name"
|
47
|
+
|
45
48
|
def export(*)
|
46
49
|
if options[:help]
|
47
50
|
invoke :help, ["export"]
|
@@ -51,9 +54,9 @@ module Rockette
|
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
54
|
-
desc "config", "
|
57
|
+
desc "config", "Set configuration options..."
|
55
58
|
method_option :help, aliases: "-h", type: :boolean,
|
56
|
-
desc: "
|
59
|
+
desc: "Not implemented yet..."
|
57
60
|
def config(*)
|
58
61
|
if options[:help]
|
59
62
|
invoke :help, ["config"]
|
@@ -62,5 +65,19 @@ module Rockette
|
|
62
65
|
Rockette::Commands::Config.new(options).execute
|
63
66
|
end
|
64
67
|
end
|
68
|
+
|
69
|
+
desc "interactive", "Start Rockette in interactive mode"
|
70
|
+
method_option :help, aliases: "-h", type: :boolean,
|
71
|
+
desc: "'rockette' by itself will start interactive mode"
|
72
|
+
def interactive(*)
|
73
|
+
if options[:help]
|
74
|
+
invoke :help, ["interactive"]
|
75
|
+
else
|
76
|
+
require_relative "commands/interactive"
|
77
|
+
Rockette::Commands::Interactive.new(options).execute
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
default_task :interactive
|
65
82
|
end
|
66
83
|
end
|
@@ -12,10 +12,37 @@ module Rockette
|
|
12
12
|
super()
|
13
13
|
@options = options
|
14
14
|
@filey = @options[:file]
|
15
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
if @options[:secret]
|
16
|
+
secret_id = @options[:secret]
|
17
|
+
signer = OCI::Auth::Signers::InstancePrincipalsSecurityTokenSigner.new
|
18
|
+
identity_client = OCI::Identity::IdentityClient.new(config: OCI::Config.new, signer: signer)
|
19
|
+
secret_client = OCI::Secrets::SecretsClient.new(config: OCI::Config.new, signer: signer)
|
20
|
+
secret_response = secret_client.get_secret_bundle(secret_id).data.secret_bundle_content.content
|
21
|
+
@conf = Psych.load(Base64.decode64(secret_response))
|
22
|
+
else
|
23
|
+
@conf = Psych.load(File.read(CONF))
|
24
|
+
end
|
25
|
+
@body = @conf["token_body"]
|
26
|
+
@hdrs = @conf["token_hdrs"]
|
27
|
+
@hdrs["Authorization"] = @conf["web_creds"][@options[:cred]] if @options[:cred]
|
28
|
+
@token = get_token
|
29
|
+
@hdrs["Authorization"] = "Bearer " + @token
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_version(filey)
|
33
|
+
app_url = "#{@options[:url]}deploy/apps/#{@options[:app_id]}"
|
34
|
+
response = Rester.new(url: app_url, headers: @hdrs).rest_try
|
35
|
+
bail unless response
|
36
|
+
abort padder("App ID: #{@options[:app_id]}, not found. Received: #{response.code}") unless response.code == 200
|
37
|
+
deployed_version = JSON.parse(response.body)["version"]
|
38
|
+
fh = File.open(filey, 'r')
|
39
|
+
export_version = ''
|
40
|
+
fh.each_line do |line|
|
41
|
+
if line.match(/,p_flow_version=>'/)
|
42
|
+
export_version = line.match(/^,p_flow_version=>'(.*?)'$/)[1]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return deployed_version == export_version
|
19
46
|
end
|
20
47
|
|
21
48
|
def file_finder
|
@@ -25,22 +52,21 @@ module Rockette
|
|
25
52
|
end
|
26
53
|
end
|
27
54
|
|
28
|
-
def
|
29
|
-
|
30
|
-
response = Rester.new(meth: "Post", params: @body, url:
|
31
|
-
|
32
|
-
abort padder("Error. Got back response code: #{response.code}") unless (200..201).include? response.code
|
33
|
-
response
|
55
|
+
def get_token
|
56
|
+
token_url = "#{@options[:url]}oauth/token"
|
57
|
+
response = Rester.new(headers: @hdrs, meth: "Post", params: @body, url: token_url).rest_try
|
58
|
+
return JSON.parse(response.body)["access_token"]
|
34
59
|
end
|
35
60
|
|
36
|
-
def
|
37
|
-
|
38
|
-
push_hdrs["file_name"] = @filey
|
39
|
-
push_url = "#{@options[:url]}data_loader/blob"
|
40
|
-
# Push the chosen export file to the target system
|
61
|
+
def deployer
|
62
|
+
push_url = "#{@options[:url]}deploy/app/#{@options[:app_id]}/"
|
41
63
|
filey = file_finder
|
42
64
|
file_not_found if filey.is_a?(Array)
|
43
|
-
|
65
|
+
if @options[:app_id] != '0' then
|
66
|
+
abort padder("Error. Versions are identical, unable to deploy export") if check_version(filey)
|
67
|
+
end
|
68
|
+
@hdrs["Content-Type"] = "application/sql"
|
69
|
+
response = Rester.new(headers: @hdrs, meth: "Post", params: File.open(filey), url: push_url).rest_try
|
44
70
|
bail unless response
|
45
71
|
abort padder("Error. Got back response code: #{response.code}") unless (200..201).include? response.code
|
46
72
|
response
|
@@ -48,13 +74,10 @@ module Rockette
|
|
48
74
|
|
49
75
|
def execute(input: $stdin, output: $stdout)
|
50
76
|
check_input(input)
|
51
|
-
|
77
|
+
filey = file_finder
|
78
|
+
file_not_found if filey.is_a?(Array)
|
52
79
|
output.puts padder("Attempting to deploy export file #{@filey}...")
|
53
|
-
|
54
|
-
output.puts padder("Pushed #{@filey} to instance and attempting import now...")
|
55
|
-
# If push was successful, request application import
|
56
|
-
sleep 1
|
57
|
-
importer
|
80
|
+
deployer
|
58
81
|
output.puts padder("Deployed #{@filey} to target APEX instance: #{@options[:url]}")
|
59
82
|
end
|
60
83
|
end
|
@@ -11,12 +11,18 @@ module Rockette
|
|
11
11
|
def initialize(options)
|
12
12
|
super()
|
13
13
|
@options = options
|
14
|
+
@conf = Psych.load(File.read(CONF))
|
15
|
+
@body = @conf["token_body"]
|
16
|
+
@hdrs = @conf["token_hdrs"]
|
17
|
+
@hdrs["Authorization"] = @conf["web_creds"][@options[:cred]] if @options[:cred]
|
14
18
|
@filey = "f#{@options[:app_id]}.sql"
|
19
|
+
@token = get_token
|
20
|
+
@hdrs["Authorization"] = "Bearer " + @token
|
15
21
|
end
|
16
22
|
|
17
23
|
def checker
|
18
24
|
app_url = "#{@options[:url]}deploy/apps/#{@options[:app_id]}"
|
19
|
-
response = Rester.new(url: app_url).rest_try
|
25
|
+
response = Rester.new(url: app_url, headers: @hdrs).rest_try
|
20
26
|
bail unless response
|
21
27
|
abort padder("App ID: #{@options[:app_id]}, not found. Received: #{response.code}") unless response.code == 200
|
22
28
|
end
|
@@ -24,32 +30,26 @@ module Rockette
|
|
24
30
|
def exporter
|
25
31
|
checker
|
26
32
|
puts padder("Found Application ID: #{@options[:app_id]}, proceeding...")
|
27
|
-
|
28
|
-
|
29
|
-
response = Rester.new(meth: "Post", params: body, url: export_url).rest_try
|
33
|
+
export_url = "#{@options[:url]}deploy/app/#{@options[:app_id]}"
|
34
|
+
response = Rester.new(url: export_url, headers: @hdrs).rest_try
|
30
35
|
bail unless response
|
31
|
-
abort padder("
|
36
|
+
abort padder("Download failed for App ID: #{@options[:app_id]}.") unless (200..201).include? response.code
|
32
37
|
response
|
33
38
|
end
|
34
39
|
|
35
|
-
def
|
36
|
-
|
37
|
-
response = Rester.new(url:
|
38
|
-
|
39
|
-
abort padder("Download failed for App ID: #{@options[:app_id]}.") unless (200..201).include? response.code
|
40
|
-
response
|
40
|
+
def get_token
|
41
|
+
token_url = "#{@options[:url]}oauth/token"
|
42
|
+
response = Rester.new(headers: @hdrs, meth: "Post", params: @body, url: token_url).rest_try
|
43
|
+
return JSON.parse(response.body)["access_token"]
|
41
44
|
end
|
42
45
|
|
43
46
|
def execute(input: $stdin, output: $stdout)
|
44
47
|
check_input(input)
|
45
|
-
|
46
|
-
exporter
|
47
|
-
output.puts padder("Export created, downloading...")
|
48
|
-
sleep 1
|
49
|
-
response = grabber
|
48
|
+
response = exporter
|
50
49
|
# Write file if export was grabbed.
|
51
|
-
|
52
|
-
|
50
|
+
save_file = @options[:file] || @filey
|
51
|
+
File.open(File.join(EXPORT_DIR, save_file), "wb") { |file| file.write(response.body) }
|
52
|
+
output.puts padder("Finished downloading #{save_file}. Have a good one!")
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
|
5
|
+
module Rockette
|
6
|
+
module Commands
|
7
|
+
# Interactive Rockette
|
8
|
+
class Interactive < Rockette::Command
|
9
|
+
include TextHelper
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
super()
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute(input: $stdin, output: $stdout)
|
17
|
+
output.puts
|
18
|
+
check_input(input)
|
19
|
+
controller = Rockette::Controller.new
|
20
|
+
controller.launch!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../text_helper"
|
4
|
+
|
5
|
+
module Rockette
|
6
|
+
# Configure Rockette application
|
7
|
+
class Configurator
|
8
|
+
include TextHelper
|
9
|
+
|
10
|
+
attr_reader :config
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@config = TTY::Config.new
|
14
|
+
@config.append_path APP_PATH
|
15
|
+
@config.read
|
16
|
+
|
17
|
+
@pastel = Pastel.new
|
18
|
+
@prompt = TTY::Prompt.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.config
|
22
|
+
@config ||= self.class.new.config
|
23
|
+
end
|
24
|
+
|
25
|
+
def launch!
|
26
|
+
puts
|
27
|
+
puts @pastel.yellow("Configure Rockette here. Choosing 'editor' will let you edit the config file directly.")
|
28
|
+
puts @pastel.yellow("Choose 'url' to enter a controller url, the api endpoint with your environments, etc.")
|
29
|
+
puts
|
30
|
+
# input/action loop
|
31
|
+
loop do
|
32
|
+
action = @prompt.select("What will it be?", %w[editor url back])
|
33
|
+
break if action == "back"
|
34
|
+
|
35
|
+
do_action(action)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def do_action(action)
|
40
|
+
case action
|
41
|
+
when "editor"
|
42
|
+
edit_config
|
43
|
+
when "url"
|
44
|
+
add_url
|
45
|
+
else
|
46
|
+
puts "\nI don't understand that command.\n\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_controller_cred
|
51
|
+
puts "Now that you have entered a controller url, please enter the OAuth client credentials for the controller."
|
52
|
+
user = @prompt.ask("User:")
|
53
|
+
pass = @prompt.ask("Pass:")
|
54
|
+
basey = 'Basic ' + Base64.encode64(user + ":" + pass).tr("\n", "")
|
55
|
+
@config.set(:rockette, :controller_cred, value: basey)
|
56
|
+
@config.write(force: true)
|
57
|
+
refresh_conf
|
58
|
+
puts "Choose View Resources and then All Applications to automate adding client credentials for each environment."
|
59
|
+
puts "You will need these credentials to use Rockette to deploy, export, and update applications."
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_url
|
63
|
+
uri = @prompt.ask("Please enter APEX deployment URI (base path):") do |u|
|
64
|
+
u.validate(%r{^https://\w+.\w+})
|
65
|
+
end
|
66
|
+
@config.set(:rockette, :controller_url, value: uri)
|
67
|
+
@config.write(force: true)
|
68
|
+
refresh_conf
|
69
|
+
end
|
70
|
+
|
71
|
+
def edit_config
|
72
|
+
edit = TTY::Editor.open(CONF)
|
73
|
+
puts "There seems to have been an issue trying to open the file: #{CONF}" unless edit
|
74
|
+
refresh_conf if edit
|
75
|
+
end
|
76
|
+
|
77
|
+
def first_run
|
78
|
+
puts
|
79
|
+
puts "I see this is your first time running Rockette. Entering an APEX deployment"
|
80
|
+
puts "uri will allow me to discover more about your environments."
|
81
|
+
puts
|
82
|
+
response = @prompt.yes?("Would you like to enter a URI?")
|
83
|
+
if response == true
|
84
|
+
add_url
|
85
|
+
add_controller_cred
|
86
|
+
else
|
87
|
+
response = @prompt.yes?("Would you like to disable these checks in the future?")
|
88
|
+
@config.set(:rockette, :check_for_url, value: false) if response == true
|
89
|
+
end
|
90
|
+
@config.write(force: true) if response == true
|
91
|
+
refresh_conf
|
92
|
+
end
|
93
|
+
|
94
|
+
def refresh_conf
|
95
|
+
@config.read
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../text_helper"
|
4
|
+
require_relative "../commands/deploy"
|
5
|
+
|
6
|
+
module Rockette
|
7
|
+
# Push APEX application to target instance
|
8
|
+
class Deployer
|
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
|
+
intro_text
|
20
|
+
|
21
|
+
# input/action loop
|
22
|
+
loop do
|
23
|
+
actions = { "🛸 Add" => 1, "📝 Update" => 2, "⬅️ Go Back" => 3 }
|
24
|
+
response = @prompt.select("Add application or update an existing application?", actions)
|
25
|
+
break if response == 3
|
26
|
+
|
27
|
+
add_app if response == 1
|
28
|
+
updater if response == 2
|
29
|
+
end
|
30
|
+
puts
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def intro_text
|
36
|
+
puts
|
37
|
+
puts @pastel.yellow("These are the two available options:")
|
38
|
+
print "1. Add application to an APEX instance. "
|
39
|
+
print "It's #{@pastel.green.bold("generally safe and creates a new application")} from the export\n"
|
40
|
+
print "2. Update an existing application with your chosen export. "
|
41
|
+
print "#{@pastel.red.bold("Tread carefully")} with this option!\n"
|
42
|
+
puts
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_app
|
46
|
+
puts padder("Let's choose an export to add")
|
47
|
+
file = choose_file
|
48
|
+
env = choose_env
|
49
|
+
url = env[0]
|
50
|
+
puts padder("You chose to add #{file} to the environment at #{url}")
|
51
|
+
puts
|
52
|
+
return unless @prompt.yes?("Proceed with the deployment?")
|
53
|
+
|
54
|
+
options = Thor::CoreExt::HashWithIndifferentAccess.new "app_id" => "0", "url" => url, "file" => file,
|
55
|
+
"cred" => env[1], "force" => true
|
56
|
+
Rockette::Commands::Deploy.new(options).execute
|
57
|
+
puts
|
58
|
+
end
|
59
|
+
|
60
|
+
def choose_app(apps_url, cred)
|
61
|
+
apps = Rockette::Viewer.new.applications(apps_url, cred)
|
62
|
+
list = list_builder(apps)
|
63
|
+
action = @prompt.slider("Application to update => ", list, default: 1)
|
64
|
+
|
65
|
+
apps[action - 1]
|
66
|
+
end
|
67
|
+
|
68
|
+
def choose_env
|
69
|
+
enviros = Rockette::Viewer.new.environments
|
70
|
+
list = list_builder(enviros)
|
71
|
+
action = @prompt.select("Which environment?", list)
|
72
|
+
[enviros[action - 1]["deployment_api"], enviros[action - 1]["web_cred"]]
|
73
|
+
end
|
74
|
+
|
75
|
+
def choose_file
|
76
|
+
list = Dir.children(EXPORT_DIR)
|
77
|
+
@prompt.select("Which export from #{EXPORT_DIR}?", list)
|
78
|
+
end
|
79
|
+
|
80
|
+
def list_builder(array)
|
81
|
+
names = [] # Start building selection list
|
82
|
+
if array[0].key?("name")
|
83
|
+
array.each { |n| names << n["name"] }
|
84
|
+
else
|
85
|
+
array.each { |n| names << "#{n["application_name"]} App ID: #{n["application_id"]}" }
|
86
|
+
end
|
87
|
+
names << "Go Back"
|
88
|
+
names.map.with_index { |n, x| [n, x + 1] }.to_h
|
89
|
+
end
|
90
|
+
|
91
|
+
def updater
|
92
|
+
puts padder("Please choose the export with your updated application code")
|
93
|
+
file = choose_file
|
94
|
+
env = choose_env
|
95
|
+
url = env[0]
|
96
|
+
app = choose_app(url, env[1])
|
97
|
+
puts "Application: #{app["application_name"]} | App ID: #{app["application_id"]} | Env URI: #{url}"
|
98
|
+
puts "will be updated with the code from export: #{file}"
|
99
|
+
puts
|
100
|
+
return unless @prompt.yes?("Proceed with the deployment?")
|
101
|
+
|
102
|
+
options = Thor::CoreExt::HashWithIndifferentAccess.new "app_id" => app["application_id"], "url" => url,
|
103
|
+
"cred" => env[1], "file" => file, "force" => true
|
104
|
+
Rockette::Commands::Deploy.new(options).execute
|
105
|
+
puts
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|