rockette 0.0.1 → 0.0.5
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 +21 -1
- data/Gemfile.lock +58 -14
- data/README.md +1 -0
- data/exe/rockette +0 -17
- data/lib/requirements.rb +21 -0
- data/lib/rockette/cli.rb +25 -6
- data/lib/rockette/commands/deploy.rb +54 -24
- data/lib/rockette/commands/export.rb +17 -18
- data/lib/rockette/commands/interactive.rb +24 -0
- data/lib/rockette/controller/configurator.rb +85 -0
- data/lib/rockette/controller/deployer.rb +106 -0
- data/lib/rockette/controller/exporter.rb +73 -0
- data/lib/rockette/controller/viewer.rb +108 -0
- data/lib/rockette/controller.rb +85 -0
- data/lib/rockette/rester.rb +79 -0
- data/lib/rockette/text_helper.rb +14 -1
- data/lib/rockette/version.rb +1 -1
- data/lib/rockette.rb +28 -84
- data/rockette.gemspec +9 -4
- data/templates/config.yml.erb +7 -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: ee0d2270c8442e3e6b696cce15e9ac765a5d2c42e6a7ab84dc2c2a9b057d90e8
|
4
|
+
data.tar.gz: 70d91cff0436629fe0cdcf50f7f5201047daee8a6504ef87a3ffc009c0143035
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c7afa7c6b7c0a4f39a4ebfa16ae70fa9b15e4a83e32930e30f2dbbae1aafa04850061de0b63e44f5023eb346e3ac42eaa68e56bd8d0a7db2b1b1cf3efc6b32f
|
7
|
+
data.tar.gz: 0ac4932e7d0302bcdf9e3df9b9c8d6c4ce12a16e0831b8de9fe947a3850ca45633fa79cbdf1409ecd833bd76a42172beb6b681128d72177421eea068d4b8c418
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -10,4 +10,24 @@
|
|
10
10
|
- Unify rest calls into Rester class
|
11
11
|
- Improve exception handling including socket errors
|
12
12
|
- Switch to yaml for config
|
13
|
-
- Use ~/.rockette as consistent location for config and exports
|
13
|
+
- Use ~/.rockette as consistent location for config and exports
|
14
|
+
|
15
|
+
## [0.0.2] - 2021-03-18
|
16
|
+
|
17
|
+
- Add copy switch to deploy command
|
18
|
+
- Use file name passed via -f switch
|
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/README.md
CHANGED
@@ -22,6 +22,7 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
Run rockette export to create and download an exported application file.
|
24
24
|
Run rockette deploy to push and import an application export.
|
25
|
+
Run rockette help or rockette 'command' help for more information.
|
25
26
|
|
26
27
|
## Development
|
27
28
|
|
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,12 +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
|
-
desc: "Provide a valid url"
|
26
|
+
desc: "Provide a valid APEX deployment url"
|
27
|
+
option :secret, aliases: "-s", required: false,
|
28
|
+
desc: "Use this flag if you are using managed secrets"
|
27
29
|
def deploy(*)
|
28
30
|
if options[:help]
|
29
31
|
invoke :help, ["deploy"]
|
@@ -40,6 +42,9 @@ module Rockette
|
|
40
42
|
desc: "Provide an APEX application ID"
|
41
43
|
option :url, aliases: "-u", required: true,
|
42
44
|
desc: "Provide a valid url"
|
45
|
+
option :file, aliases: "-f", required: false,
|
46
|
+
desc: "Save export with this file name"
|
47
|
+
|
43
48
|
def export(*)
|
44
49
|
if options[:help]
|
45
50
|
invoke :help, ["export"]
|
@@ -49,9 +54,9 @@ module Rockette
|
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
52
|
-
desc "config", "
|
57
|
+
desc "config", "Set configuration options..."
|
53
58
|
method_option :help, aliases: "-h", type: :boolean,
|
54
|
-
desc: "
|
59
|
+
desc: "Not implemented yet..."
|
55
60
|
def config(*)
|
56
61
|
if options[:help]
|
57
62
|
invoke :help, ["config"]
|
@@ -60,5 +65,19 @@ module Rockette
|
|
60
65
|
Rockette::Commands::Config.new(options).execute
|
61
66
|
end
|
62
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
|
63
82
|
end
|
64
83
|
end
|
@@ -11,28 +11,61 @@ module Rockette
|
|
11
11
|
def initialize(options)
|
12
12
|
super()
|
13
13
|
@options = options
|
14
|
-
@filey =
|
14
|
+
@filey = @options[:file]
|
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 = JSON.parse(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
|
+
@token = get_token
|
28
|
+
@hdrs["Authorization"] = "Bearer " + @token
|
29
|
+
@hdrs["Content-Type"] = "application/sql"
|
15
30
|
end
|
16
31
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
body["app_id_tgt"] = @options[:app_id]
|
21
|
-
# body["app_id_tgt"] = "0" #test app copy
|
22
|
-
url = "#{@options[:url]}deploy/app"
|
23
|
-
response = Rester.new(meth: "Post", params: body, url: url).rest_try
|
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
|
24
35
|
bail unless response
|
25
|
-
abort padder("
|
26
|
-
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
|
46
|
+
end
|
47
|
+
|
48
|
+
def file_finder
|
49
|
+
[EXPORT_DIR, "/usr/app", "/usr/local/app"].each do |f|
|
50
|
+
next unless File.exist?(File.join(f, @filey))
|
51
|
+
break File.join(f, @filey) if File.exist?(File.join(f, @filey)) # Take 1st match
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
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"]
|
27
59
|
end
|
28
60
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
61
|
+
def deployer
|
62
|
+
push_url = "#{@options[:url]}deploy/app/#{@options[:app_id]}/"
|
63
|
+
filey = file_finder
|
64
|
+
file_not_found if filey.is_a?(Array)
|
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
|
+
response = Rester.new(headers: @hdrs, meth: "Post", params: File.open(filey), url: push_url).rest_try
|
36
69
|
bail unless response
|
37
70
|
abort padder("Error. Got back response code: #{response.code}") unless (200..201).include? response.code
|
38
71
|
response
|
@@ -40,13 +73,10 @@ module Rockette
|
|
40
73
|
|
41
74
|
def execute(input: $stdin, output: $stdout)
|
42
75
|
check_input(input)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# If push was successful, request application import
|
48
|
-
sleep 1
|
49
|
-
importer
|
76
|
+
filey = file_finder
|
77
|
+
file_not_found if filey.is_a?(Array)
|
78
|
+
output.puts padder("Attempting to deploy export file #{@filey}...")
|
79
|
+
deployer
|
50
80
|
output.puts padder("Deployed #{@filey} to target APEX instance: #{@options[:url]}")
|
51
81
|
end
|
52
82
|
end
|
@@ -11,12 +11,17 @@ 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"]
|
14
17
|
@filey = "f#{@options[:app_id]}.sql"
|
18
|
+
@token = get_token
|
19
|
+
@hdrs["Authorization"] = "Bearer " + @token
|
15
20
|
end
|
16
21
|
|
17
22
|
def checker
|
18
23
|
app_url = "#{@options[:url]}deploy/apps/#{@options[:app_id]}"
|
19
|
-
response = Rester.new(url: app_url).rest_try
|
24
|
+
response = Rester.new(url: app_url, headers: @hdrs).rest_try
|
20
25
|
bail unless response
|
21
26
|
abort padder("App ID: #{@options[:app_id]}, not found. Received: #{response.code}") unless response.code == 200
|
22
27
|
end
|
@@ -24,32 +29,26 @@ module Rockette
|
|
24
29
|
def exporter
|
25
30
|
checker
|
26
31
|
puts padder("Found Application ID: #{@options[:app_id]}, proceeding...")
|
27
|
-
|
28
|
-
|
29
|
-
response = Rester.new(meth: "Post", params: body, url: export_url).rest_try
|
32
|
+
export_url = "#{@options[:url]}deploy/app/#{@options[:app_id]}"
|
33
|
+
response = Rester.new(url: export_url, headers: @hdrs).rest_try
|
30
34
|
bail unless response
|
31
|
-
abort padder("
|
35
|
+
abort padder("Download failed for App ID: #{@options[:app_id]}.") unless (200..201).include? response.code
|
32
36
|
response
|
33
37
|
end
|
34
38
|
|
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
|
39
|
+
def get_token
|
40
|
+
token_url = "#{@options[:url]}oauth/token"
|
41
|
+
response = Rester.new(headers: @hdrs, meth: "Post", params: @body, url: token_url).rest_try
|
42
|
+
return JSON.parse(response.body)["access_token"]
|
41
43
|
end
|
42
44
|
|
43
45
|
def execute(input: $stdin, output: $stdout)
|
44
46
|
check_input(input)
|
45
|
-
|
46
|
-
exporter
|
47
|
-
output.puts padder("Export created, downloading...")
|
48
|
-
sleep 1
|
49
|
-
response = grabber
|
47
|
+
response = exporter
|
50
48
|
# Write file if export was grabbed.
|
51
|
-
|
52
|
-
|
49
|
+
save_file = @options[:file] || @filey
|
50
|
+
File.open(File.join(EXPORT_DIR, save_file), "wb") { |file| file.write(response.body) }
|
51
|
+
output.puts padder("Finished downloading #{save_file}. Have a good one!")
|
53
52
|
end
|
54
53
|
end
|
55
54
|
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,85 @@
|
|
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_url
|
51
|
+
uri = @prompt.ask("Please enter APEX deployment URI (base path):") do |u|
|
52
|
+
u.validate(%r{^https://\w+.\w+})
|
53
|
+
end
|
54
|
+
@config.set(:rockette, :controller_url, value: uri)
|
55
|
+
@config.write(force: true)
|
56
|
+
refresh_conf
|
57
|
+
end
|
58
|
+
|
59
|
+
def edit_config
|
60
|
+
edit = TTY::Editor.open(CONF)
|
61
|
+
puts "There seems to have been an issue trying to open the file: #{CONF}" unless edit
|
62
|
+
refresh_conf if edit
|
63
|
+
end
|
64
|
+
|
65
|
+
def first_run
|
66
|
+
puts
|
67
|
+
puts "I see this is your first time running Rockette. Entering an APEX deployment"
|
68
|
+
puts "uri will allow me to discover more about your environments."
|
69
|
+
puts
|
70
|
+
response = @prompt.yes?("Would you like to enter a URI?")
|
71
|
+
if response == true
|
72
|
+
add_url
|
73
|
+
else
|
74
|
+
response = @prompt.yes?("Would you like to disable these checks in the future?")
|
75
|
+
@config.set(:rockette, :check_for_url, value: false) if response == true
|
76
|
+
end
|
77
|
+
@config.write(force: true) if response == true
|
78
|
+
refresh_conf
|
79
|
+
end
|
80
|
+
|
81
|
+
def refresh_conf
|
82
|
+
@config.read
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,106 @@
|
|
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
|
+
url = choose_env
|
49
|
+
puts padder("You chose to add #{file} to the environment at #{url}")
|
50
|
+
puts
|
51
|
+
return unless @prompt.yes?("Proceed with the deployment?")
|
52
|
+
|
53
|
+
options = Thor::CoreExt::HashWithIndifferentAccess.new "app_id" => "0", "url" => url, "file" => file,
|
54
|
+
"force" => true
|
55
|
+
Rockette::Commands::Deploy.new(options).execute
|
56
|
+
puts
|
57
|
+
end
|
58
|
+
|
59
|
+
def choose_app(apps_url)
|
60
|
+
apps = Rockette::Viewer.new.applications(apps_url)
|
61
|
+
list = list_builder(apps)
|
62
|
+
action = @prompt.slider("Application to update => ", list, default: 1)
|
63
|
+
|
64
|
+
apps[action - 1]
|
65
|
+
end
|
66
|
+
|
67
|
+
def choose_env
|
68
|
+
enviros = Rockette::Viewer.new.environments
|
69
|
+
list = list_builder(enviros)
|
70
|
+
action = @prompt.select("Which environment?", list)
|
71
|
+
enviros[action - 1]["deployment_api"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def choose_file
|
75
|
+
list = Dir.children(EXPORT_DIR)
|
76
|
+
@prompt.select("Which export from #{EXPORT_DIR}?", list)
|
77
|
+
end
|
78
|
+
|
79
|
+
def list_builder(array)
|
80
|
+
names = [] # Start building selection list
|
81
|
+
if array[0].key?("name")
|
82
|
+
array.each { |n| names << n["name"] }
|
83
|
+
else
|
84
|
+
array.each { |n| names << "#{n["application_name"]} App ID: #{n["application_id"]}" }
|
85
|
+
end
|
86
|
+
names << "Go Back"
|
87
|
+
names.map.with_index { |n, x| [n, x + 1] }.to_h
|
88
|
+
end
|
89
|
+
|
90
|
+
def updater
|
91
|
+
puts padder("Please choose the export with your updated application code")
|
92
|
+
file = choose_file
|
93
|
+
url = choose_env
|
94
|
+
app = choose_app(url)
|
95
|
+
puts "Application: #{app["application_name"]} | App ID: #{app["application_id"]} | Env URI: #{url}"
|
96
|
+
puts "will be updated with the code from export: #{file}"
|
97
|
+
puts
|
98
|
+
return unless @prompt.yes?("Proceed with the deployment?")
|
99
|
+
|
100
|
+
options = Thor::CoreExt::HashWithIndifferentAccess.new "app_id" => app["application_id"], "url" => url,
|
101
|
+
"file" => file, "force" => true
|
102
|
+
Rockette::Commands::Deploy.new(options).execute
|
103
|
+
puts
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|