gleis 0.1.0
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 +7 -0
- data/LICENSE +674 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/gleis +7 -0
- data/lib/gleis/addon.rb +41 -0
- data/lib/gleis/api.rb +45 -0
- data/lib/gleis/application.rb +198 -0
- data/lib/gleis/authentication.rb +47 -0
- data/lib/gleis/cli/addon.rb +23 -0
- data/lib/gleis/cli/app.rb +73 -0
- data/lib/gleis/cli/auth.rb +21 -0
- data/lib/gleis/cli/db.rb +48 -0
- data/lib/gleis/cli/domain.rb +23 -0
- data/lib/gleis/cli/management.rb +16 -0
- data/lib/gleis/cli/sharing.rb +23 -0
- data/lib/gleis/cli/storage.rb +28 -0
- data/lib/gleis/config.rb +21 -0
- data/lib/gleis/database.rb +126 -0
- data/lib/gleis/domain.rb +39 -0
- data/lib/gleis/main.rb +36 -0
- data/lib/gleis/management.rb +42 -0
- data/lib/gleis/params.rb +9 -0
- data/lib/gleis/sharing.rb +38 -0
- data/lib/gleis/ssh.rb +36 -0
- data/lib/gleis/storage.rb +69 -0
- data/lib/gleis/token.rb +21 -0
- data/lib/gleis/utils.rb +105 -0
- data/lib/gleis/version.rb +3 -0
- data/lib/gleis.rb +29 -0
- metadata +188 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
module Gleis
|
2
|
+
# The class implements the methods required for the databases of a gleis app
|
3
|
+
class Database
|
4
|
+
def self.backup(app_name)
|
5
|
+
token = Token.check
|
6
|
+
Utils.check_for_local_pg_command('pg_dump')
|
7
|
+
url = Config.get_env_var(app_name, token, 'DATABASE_URL')
|
8
|
+
abort('There is no database configured under the DATABASE_URL variable.') unless url
|
9
|
+
db_name = url.split('/').last
|
10
|
+
timestamp = Time.now.strftime('%Y%m%d%H%M%S')
|
11
|
+
backup_file = "/tmp/#{app_name}_#{db_name}_#{timestamp}.pgdump"
|
12
|
+
if system("pg_dump -f #{backup_file} #{url}")
|
13
|
+
puts "Database configured at DATABASE_URL succesfully backed up locally in #{backup_file}"
|
14
|
+
else
|
15
|
+
puts 'Failed to backup database configured under DATABASE_URL'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.delete(app_name, env_var_name)
|
20
|
+
token = Token.check
|
21
|
+
if Utils.prompt_confirmation("Are you sure you want to delete the database at #{env_var_name}?")
|
22
|
+
body = API.request('delete', "db/#{app_name}/#{env_var_name}", token)
|
23
|
+
if body['success'] == 1
|
24
|
+
puts "Successfully deleted database configured at #{env_var_name}."
|
25
|
+
else
|
26
|
+
puts "Failed to delete database: #{body['message']}"
|
27
|
+
end
|
28
|
+
else
|
29
|
+
puts 'Command cancelled'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.info(app_name)
|
34
|
+
token = Token.check
|
35
|
+
url = Config.get_env_var(app_name, token, 'DATABASE_URL')
|
36
|
+
abort_message = 'You do not have a database or you did not promote it yet. '\
|
37
|
+
'You can create one with the db:new command and promote it with db:promote.'
|
38
|
+
abort(abort_message) unless url
|
39
|
+
# Get database info
|
40
|
+
db_name = url.split('/').last
|
41
|
+
body = API.request('get', "database/#{db_name}", token)
|
42
|
+
return unless body['success'] == 1
|
43
|
+
|
44
|
+
db = body['database']
|
45
|
+
puts "Info about database at DATABASE_URL:\n\n"
|
46
|
+
puts "\tName:\t\t#{db['name']}\n" \
|
47
|
+
"\tCreated on:\t#{Time.parse(db['created_at']).strftime('%c')}"
|
48
|
+
if body['available']
|
49
|
+
puts "\tStatus:\t\tavailable\n" \
|
50
|
+
"\tDatabase:\t#{body['version']}\n" \
|
51
|
+
"\tConnections:\t#{body['connections']}"
|
52
|
+
else
|
53
|
+
puts "\tStatus:\t\tnot available"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.new(app_name)
|
58
|
+
token = Token.check
|
59
|
+
body = API.request('post', 'db', token, 'name': app_name)
|
60
|
+
if body['success'] == 1
|
61
|
+
puts "Successfully created new database for #{app_name} available as config variable #{body['message']}"
|
62
|
+
else
|
63
|
+
puts 'Failed to create new database'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.promote(app_name, env_var_name)
|
68
|
+
token = Token.check
|
69
|
+
body = API.request('post', 'db/promote', token, 'name': app_name, 'var': env_var_name)
|
70
|
+
if body['success'] == 1
|
71
|
+
puts "Succesfully promoted database environment variable #{env_var_name} to DATABASE_URL"
|
72
|
+
else
|
73
|
+
puts 'Failed to promote database environment variable'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.push(app_name, local_name)
|
78
|
+
token = Token.check
|
79
|
+
Utils.check_for_local_pg_command('pg_dump')
|
80
|
+
Utils.check_for_local_pg_command('pg_restore')
|
81
|
+
url = Config.get_env_var(app_name, token, 'DATABASE_URL')
|
82
|
+
abort('There is no database configured under the DATABASE_URL variable.') unless url
|
83
|
+
ENV['PGCONNECT_TIMEOUT'] = '5'
|
84
|
+
# Check if database is empty
|
85
|
+
sql_statement = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public'"
|
86
|
+
table_count = `psql #{url} -t -A -c "#{sql_statement}"`.chomp
|
87
|
+
if table_count.to_i.zero?
|
88
|
+
# Check connection to local database
|
89
|
+
unless system("psql -c 'SELECT 1' #{local_name} >/dev/null 2>&1")
|
90
|
+
abort("Failed to connect to local database #{local_name}, please check " \
|
91
|
+
'that the database name is correct and that you have access to it.')
|
92
|
+
end
|
93
|
+
if system("pg_dump -Fc -x #{local_name} | pg_restore -O -n public -d #{url}")
|
94
|
+
puts "Successfully pushed local database #{local_name} to database configured at DATABASE_URL."
|
95
|
+
else
|
96
|
+
puts "Failed to push local database #{local_name} to DATABASE_URL."
|
97
|
+
end
|
98
|
+
else
|
99
|
+
puts 'The database configured at DATABASE_URL already contains data, please empty it first.'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.psql(app_name)
|
104
|
+
token = Token.check
|
105
|
+
abort('The PostgreSQL client psql is not installed on this system.') unless system('which psql >/dev/null')
|
106
|
+
url = Config.get_env_var(app_name, token, 'DATABASE_URL')
|
107
|
+
abort('There is no database configured under the DATABASE_URL variable.') unless url
|
108
|
+
ENV['PGCONNECT_TIMEOUT'] = '5'
|
109
|
+
exec("psql #{url}")
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.reset(app_name, env_var_name)
|
113
|
+
token = Token.check
|
114
|
+
if Utils.prompt_confirmation("Are you sure you want to reset the database at #{env_var_name}?")
|
115
|
+
body = API.request('put', 'db', token, 'name': app_name, 'var': env_var_name)
|
116
|
+
if body['success'] == 1
|
117
|
+
puts "Successfully reset database configured at #{env_var_name}."
|
118
|
+
else
|
119
|
+
puts "Failed to delete database: #{body['message']}"
|
120
|
+
end
|
121
|
+
else
|
122
|
+
puts 'Command cancelled'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/gleis/domain.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Gleis
|
2
|
+
# The class implements the methods required to manage the domain names of a gleis app
|
3
|
+
class Domain
|
4
|
+
def self.add(app_name, name)
|
5
|
+
token = Token.check
|
6
|
+
body = API.request('post', 'domains', token, 'name': app_name, 'domain': name)
|
7
|
+
if body['success'] == 1
|
8
|
+
puts "Successfully added domain to #{app_name}."
|
9
|
+
else
|
10
|
+
puts "Failed to add domain: #{body['message']}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.list(app_name)
|
15
|
+
token = Token.check
|
16
|
+
body = API.request('get', "domains/#{app_name}", token)
|
17
|
+
puts "Your app is available under the URL: https://#{body['fqdn']}\n\n"
|
18
|
+
domains = body ['data']
|
19
|
+
if domains.any?
|
20
|
+
puts "Domain list for #{app_name}:\n\n"
|
21
|
+
domains.each do |domain|
|
22
|
+
puts "\t#{domain['name']}"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
puts 'No domains defined yet.'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.remove(app_name, name)
|
30
|
+
token = Token.check
|
31
|
+
body = API.request('delete', "domains/#{app_name}/#{name}", token)
|
32
|
+
if body['success'] == 1
|
33
|
+
puts "Successfully removed domain name from #{app_name}."
|
34
|
+
else
|
35
|
+
puts "Failed to remove domain name: #{body['message']}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/gleis/main.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gleis'
|
3
|
+
|
4
|
+
module Gleis
|
5
|
+
# This class defines all the main command-line interface commands for gleis
|
6
|
+
class Main < Thor
|
7
|
+
desc 'login USERNAME', 'Login into Gleis'
|
8
|
+
def login(username)
|
9
|
+
Authentication.login(username)
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'addon COMMAND', 'Manage add-ons: add, list, remove'
|
13
|
+
subcommand 'addon', CLI::Addon
|
14
|
+
|
15
|
+
desc 'app COMMAND', 'Manage applications: create, start, stop, logs, etc.'
|
16
|
+
subcommand 'app', CLI::App
|
17
|
+
|
18
|
+
desc 'auth COMMAND', 'Authentication commands: login, logout, whoami'
|
19
|
+
subcommand 'auth', CLI::Auth
|
20
|
+
|
21
|
+
desc 'db COMMAND', 'Manage databases: info, new, promote, psql, etc.'
|
22
|
+
subcommand 'db', CLI::Db
|
23
|
+
|
24
|
+
desc 'domain COMMAND', 'Manage domains: add, list, remove'
|
25
|
+
subcommand 'domain', CLI::Domain
|
26
|
+
|
27
|
+
desc 'mgmt COMMAND', 'Administration and management related commands'
|
28
|
+
subcommand 'mgmt', CLI::Management
|
29
|
+
|
30
|
+
desc 'sharing COMMAND', 'Manage collaboration: add, list, remove'
|
31
|
+
subcommand 'sharing', CLI::Sharing
|
32
|
+
|
33
|
+
desc 'storage COMMAND', 'Manage persistent storage: add, list, sync, etc.'
|
34
|
+
subcommand 'storage', CLI::Storage
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Gleis
|
2
|
+
# The class implements management and administrative methods around the Gleis platform
|
3
|
+
class Management
|
4
|
+
def self.apps
|
5
|
+
token = Token.check
|
6
|
+
body = API.request('get', 'mgmt/apps', token)
|
7
|
+
apps = body ['data']
|
8
|
+
if apps.any?
|
9
|
+
puts "Apps list for your organisation:\n\n"
|
10
|
+
printf("\t%-39s %-25s %s\n", 'APP NAME', 'CREATED ON', 'PLAN')
|
11
|
+
printf("\t%-39s %-25s %s\n\n", '--------', '----------', '----')
|
12
|
+
apps.each do |app|
|
13
|
+
printf("\t%-39s %-25s %s\n", app['name'], Time.parse(app['created_at']).localtime.strftime('%c'),
|
14
|
+
app['plan_name'].capitalize)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
puts 'No apps found.'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.license
|
22
|
+
puts <<LICENSE
|
23
|
+
Gleis Command Line Interface for the Gleis Platform as a Service
|
24
|
+
Copyright (C) 2018 towards GmbH
|
25
|
+
|
26
|
+
This program is free software: you can redistribute it and/or modify
|
27
|
+
it under the terms of the GNU General Public License as published by
|
28
|
+
the Free Software Foundation, either version 3 of the License, or
|
29
|
+
(at your option) any later version.
|
30
|
+
|
31
|
+
This program is distributed in the hope that it will be useful,
|
32
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
33
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
34
|
+
GNU General Public License for more details.
|
35
|
+
|
36
|
+
You should have received a copy of the GNU General Public License
|
37
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
38
|
+
|
39
|
+
LICENSE
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/gleis/params.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gleis
|
2
|
+
# The class implements the methods required for collaborating on a gleis app
|
3
|
+
class Sharing
|
4
|
+
def self.add(app_name, email, role)
|
5
|
+
token = Token.check
|
6
|
+
body = API.request('post', 'sharing', token, 'name': app_name, 'email': email, 'role': role)
|
7
|
+
if body['success'] == 1
|
8
|
+
puts "Successfully added user to access list for #{app_name}."
|
9
|
+
else
|
10
|
+
puts "Failed to add user to access list: #{body['message']}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.list(app_name)
|
15
|
+
token = Token.check
|
16
|
+
body = API.request('get', "sharing/#{app_name}", token)
|
17
|
+
acls = body ['acl']
|
18
|
+
if acls.any?
|
19
|
+
puts "Access list for #{app_name}:\n\n"
|
20
|
+
acls.each do |acl|
|
21
|
+
printf("\t%-45s %s\n", acl['user_name'], acl['role_name'])
|
22
|
+
end
|
23
|
+
else
|
24
|
+
puts 'No access list defined yet.'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.remove(app_name, email)
|
29
|
+
token = Token.check
|
30
|
+
body = API.request('delete', "sharing/#{app_name}/#{email}", token)
|
31
|
+
if body['success'] == 1
|
32
|
+
puts "Successfully removed user from access list for #{app_name}."
|
33
|
+
else
|
34
|
+
puts "Failed to remove user from access list: #{body['message']}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/gleis/ssh.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Gleis
|
4
|
+
# This class manages the SSH config and keys on the client side
|
5
|
+
class SSH
|
6
|
+
def self.generate_key(key_file, username)
|
7
|
+
return if File.exist?(key_file)
|
8
|
+
|
9
|
+
puts 'Could not find an existing public/private key pair'
|
10
|
+
return unless Utils.prompt_yes_no('Would you like to generate one now?')
|
11
|
+
|
12
|
+
hostname = Socket.gethostname
|
13
|
+
datetime = Time.now.strftime('%Y-%m-%d %H:%M')
|
14
|
+
# returns true on success
|
15
|
+
system('ssh-keygen', '-f', key_file, '-b 4096',
|
16
|
+
"-C generated by Gleis CLI for #{username} by #{ENV['USER']}@#{hostname} on #{datetime}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.load_public_key(key_file)
|
20
|
+
public_key_file = key_file + '.pub'
|
21
|
+
return File.read(public_key_file).chomp if File.exist?(public_key_file)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.add_host_to_config(git_host, run_host, key_file)
|
25
|
+
config_file = Dir.home + '/.ssh/config'
|
26
|
+
ssh_host_line = "Host #{git_host} #{run_host}"
|
27
|
+
# Check if SSH config for hosts already exists
|
28
|
+
return if Utils.line_exists_in_file(key_file, ssh_host_line)
|
29
|
+
|
30
|
+
f = File.open(config_file, 'a')
|
31
|
+
f.puts ssh_host_line
|
32
|
+
f.puts "\tIdentityFile #{key_file}"
|
33
|
+
f.close
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Gleis
|
2
|
+
# The class implements the methods required to the storage of a gleis app
|
3
|
+
class Storage
|
4
|
+
def self.add(app_name, type)
|
5
|
+
token = Token.check
|
6
|
+
body = API.request('post', 'storage', token, 'name': app_name, 'type': type)
|
7
|
+
if body['success'] == 1
|
8
|
+
puts "Successfully added #{type} storage to #{app_name}. As soon as you restart " \
|
9
|
+
"your app the storage will be available under the #{body['mount_target']} directory."
|
10
|
+
else
|
11
|
+
puts "Failed to add storage: #{body['message']}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.attach(app_name, dir)
|
16
|
+
token = Token.check
|
17
|
+
body = API.request('post', 'storage/attach', token, 'name': app_name, 'dir': dir)
|
18
|
+
if body['success'] == 1
|
19
|
+
puts "Successfully attached storage to #{dir} directory. As soon as you restart your app " \
|
20
|
+
'the storage will be available under this directory.'
|
21
|
+
else
|
22
|
+
puts "Failed to attach storage: #{body['message']}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.list(app_name)
|
27
|
+
token = Token.check
|
28
|
+
action = 'storage/' + app_name
|
29
|
+
body = API.request('get', action, token)
|
30
|
+
puts "Available storage types:\n\n"
|
31
|
+
printf("\t%-8s %s\n", 'TYPE', 'DESCRIPTION')
|
32
|
+
printf("\t%-8s %s\n\n", '----', '-----------')
|
33
|
+
body['data']['storage_types'].each do |st|
|
34
|
+
printf("\t%-8s %s\n", st['name'], st['description'])
|
35
|
+
end
|
36
|
+
if body['data']['storage'].any?
|
37
|
+
puts "\nStorage in use by app:\n\n"
|
38
|
+
printf("\t%-8s %-30s %-25s %s\n", 'TYPE', 'MOUNT TARGET', 'CREATED ON', 'USAGE')
|
39
|
+
printf("\t%-8s %-30s %-25s %s\n\n", '----', '------------', '-----------', '-----')
|
40
|
+
body['data']['storage'].each do |s|
|
41
|
+
printf("\t%-8s %-30s %-25s %s\n", s['storage_type_name'], s['mount_target'],
|
42
|
+
Time.parse(s['created_at']).localtime.strftime('%c'), s['usage'])
|
43
|
+
end
|
44
|
+
else
|
45
|
+
puts "\nYour app is not currently using any storage."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.sync(app_name, dir)
|
50
|
+
token = Token.check
|
51
|
+
abort("Directory #{dir} does not exist or is not a directory.") unless Dir.exist?(dir)
|
52
|
+
# Get CLI parameters from API server
|
53
|
+
params = Params.get_cli_parameters(token)
|
54
|
+
abort('The rsync tool is not installed on this system.') unless system('which rsync >/dev/null')
|
55
|
+
body = API.request('get', "storage/#{app_name}", token)
|
56
|
+
if body['success'] == 1
|
57
|
+
if body['storage']
|
58
|
+
ns_app_name = "#{body['namespace']}_#{app_name}"
|
59
|
+
ENV['RSYNC_PASSWORD'] = body['storage']['password']
|
60
|
+
exec("rsync -rth --progress #{dir}/ rsync://#{ns_app_name}@#{params['sync_server']}/#{ns_app_name}")
|
61
|
+
else
|
62
|
+
puts 'No storage configured yet.'
|
63
|
+
end
|
64
|
+
else
|
65
|
+
puts 'Failed to get storage info.'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/gleis/token.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gleis
|
2
|
+
# This class manages the authentication token granted from the API server
|
3
|
+
class Token
|
4
|
+
def self.save(token)
|
5
|
+
abort('No tokens received.') unless token
|
6
|
+
f = File.new(Config::TOKEN_FILE, 'w', 0o0640)
|
7
|
+
f.write(token)
|
8
|
+
f.close
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.check
|
12
|
+
return File.read(Config::TOKEN_FILE) if File.exist?(Config::TOKEN_FILE)
|
13
|
+
|
14
|
+
abort('Not authenticated, please login first.')
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.delete
|
18
|
+
File.delete(Config::TOKEN_FILE) if File.exist?(Config::TOKEN_FILE)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/gleis/utils.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
module Gleis
|
2
|
+
# This class gathers various utilities as small methods
|
3
|
+
class Utils
|
4
|
+
def self.convert_username_to_filename(username)
|
5
|
+
username.sub('@', '_at_').tr('.', '_')
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.prompt_password
|
9
|
+
print 'Password: '
|
10
|
+
system 'stty -echo'
|
11
|
+
password = $stdin.gets.chomp
|
12
|
+
system 'stty echo'
|
13
|
+
puts
|
14
|
+
password
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.prompt_yes_no(text)
|
18
|
+
loop do
|
19
|
+
print text + ' [y/n]: '
|
20
|
+
case STDIN.gets.strip
|
21
|
+
when 'Y', 'y', 'yes'
|
22
|
+
return true
|
23
|
+
when /\A[nN]o?\Z/
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.app_name
|
30
|
+
Dir.pwd.split('/').last
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.check_for_local_pg_command(command)
|
34
|
+
abort("The PostgreSQL client required to run the command #{command}) is not installed on this system.") unless
|
35
|
+
system("which #{command} >/dev/null")
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.validate_scale_count(count)
|
39
|
+
count_i = count.to_i
|
40
|
+
abort('Please specifiy a number between 1 and 10 as parameter in order to scale your app.') unless
|
41
|
+
count_i&.between?(1, 10)
|
42
|
+
count_i
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.add_remote_to_git_config(remote_url)
|
46
|
+
config_file = Dir.pwd + '/.git/config'
|
47
|
+
return false unless File.exist?(config_file)
|
48
|
+
|
49
|
+
# Check if gleis remote already exists
|
50
|
+
git_remote_line = '[remote "gleis"]'
|
51
|
+
return if line_exists_in_file(config_file, git_remote_line)
|
52
|
+
|
53
|
+
f = File.open(config_file, 'a')
|
54
|
+
f.puts "\n#{git_remote_line}"
|
55
|
+
f.puts "\turl = #{remote_url}"
|
56
|
+
f.puts "\tfetch = +refs/heads/*:refs/remotes/origin/*"
|
57
|
+
f.close
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.line_exists_in_file(file, line)
|
61
|
+
File.readlines(file).grep(/#{Regexp.escape(line)}/).size.positive?
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.prompt_confirmation(text)
|
65
|
+
print 'WARNING: ' + text + ' (write YES in uppercase to confirm): '
|
66
|
+
answer = STDIN.gets.chomp
|
67
|
+
answer == 'YES'
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.output_tasks(tasks, type)
|
71
|
+
tasks.each do |task|
|
72
|
+
timestamp_formatted = Time.parse(task['timestamp']).localtime.strftime('%c')
|
73
|
+
puts "#{type}.#{task['slot']}: #{task['status']} #{timestamp_formatted}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.output_config_env_vars(env_vars, app_name)
|
78
|
+
puts "Configuration (environment variables) for #{app_name}:\n\n"
|
79
|
+
env_vars.each do |key, value|
|
80
|
+
puts "\t#{key}=#{value}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.generate_docker_cmd_env_vars(env_vars)
|
85
|
+
env_vars_param = ''
|
86
|
+
env_vars.each do |key, value|
|
87
|
+
env_vars_param << " -e #{key}=#{value}"
|
88
|
+
end
|
89
|
+
env_vars_param
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.generate_docker_cmd_mount(body, app_name)
|
93
|
+
mount_param = ''
|
94
|
+
if body['success'] == 1
|
95
|
+
storage_type = body['storage_type']
|
96
|
+
if storage_type
|
97
|
+
storage = body['storage']
|
98
|
+
mount_src = "#{storage_type['mount_source']}/#{body['namespace']}/#{app_name}"
|
99
|
+
mount_param = "--mount type=#{storage_type['mount_type']},src=#{mount_src},dst=#{storage['mount_target']}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
mount_param
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/gleis.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'gleis/utils'
|
2
|
+
require 'gleis/authentication'
|
3
|
+
require 'gleis/addon'
|
4
|
+
require 'gleis/api'
|
5
|
+
require 'gleis/application'
|
6
|
+
require 'gleis/cli/addon'
|
7
|
+
require 'gleis/cli/app'
|
8
|
+
require 'gleis/cli/auth'
|
9
|
+
require 'gleis/cli/db'
|
10
|
+
require 'gleis/cli/domain'
|
11
|
+
require 'gleis/cli/management'
|
12
|
+
require 'gleis/cli/sharing'
|
13
|
+
require 'gleis/cli/storage'
|
14
|
+
require 'gleis/config'
|
15
|
+
require 'gleis/database'
|
16
|
+
require 'gleis/domain'
|
17
|
+
require 'gleis/management'
|
18
|
+
require 'gleis/params'
|
19
|
+
require 'gleis/sharing'
|
20
|
+
require 'gleis/ssh'
|
21
|
+
require 'gleis/storage'
|
22
|
+
require 'gleis/token'
|
23
|
+
require 'gleis/version'
|
24
|
+
|
25
|
+
require 'json'
|
26
|
+
|
27
|
+
# Top-level gleis module namespace
|
28
|
+
module Gleis
|
29
|
+
end
|