rockette 0.0.2 → 0.0.6
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/.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
|