vmc_knife 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/vmc_knife/cli_extensions.rb +59 -11
- data/lib/vmc_knife/commands/knife_cmds.rb +42 -9
- data/lib/vmc_knife/data_services.rb +364 -0
- data/lib/vmc_knife/vmc_knife.rb +41 -11
- data/lib/vmc_knife.rb +1 -0
- metadata +5 -4
@@ -72,8 +72,8 @@ class VMC::Cli::KnifeRunner < VMC::Cli::Runner
|
|
72
72
|
else
|
73
73
|
set_cmd(:knife, :configure_etc_avahi_aliases, @args.size) # too many
|
74
74
|
end
|
75
|
-
when 'configure-applications'
|
76
|
-
usage('vmc_knife configure-
|
75
|
+
when 'configure-applications','configure-apps'
|
76
|
+
usage('vmc_knife configure-apps [<applications_regexp>]')
|
77
77
|
@args.shift # consumes the argument.
|
78
78
|
if @args.size <= 2
|
79
79
|
set_cmd(:knifeapps, :configure_applications, @args.size)
|
@@ -96,32 +96,32 @@ class VMC::Cli::KnifeRunner < VMC::Cli::Runner
|
|
96
96
|
else
|
97
97
|
set_cmd(:knifeapps, :configure_recipes, @args.size) # too many
|
98
98
|
end
|
99
|
-
when 'upload-applications'
|
100
|
-
usage('vmc_knife upload-
|
99
|
+
when 'upload-applications','upload-apps'
|
100
|
+
usage('vmc_knife upload-apps [<applications_regexp>]')
|
101
101
|
@args.shift # consumes the argument.
|
102
102
|
if @args.size <= 2
|
103
103
|
set_cmd(:knifeapps, :upload_applications, @args.size)
|
104
104
|
else
|
105
105
|
set_cmd(:knifeapps, :upload_applications, @args.size) # too many
|
106
106
|
end
|
107
|
-
when 'start-applications'
|
108
|
-
usage('vmc_knife start-
|
107
|
+
when 'start-applications','start-apps'
|
108
|
+
usage('vmc_knife start-apps [<applications_regexp>]')
|
109
109
|
@args.shift # consumes the argument.
|
110
110
|
if @args.size <= 2
|
111
111
|
set_cmd(:knifeapps, :start_applications, @args.size)
|
112
112
|
else
|
113
113
|
set_cmd(:knifeapps, :start_applications, @args.size) # too many
|
114
114
|
end
|
115
|
-
when 'stop-applications'
|
116
|
-
usage('vmc_knife stop-
|
115
|
+
when 'stop-applications','stop-apps'
|
116
|
+
usage('vmc_knife stop-apps [<applications_regexp>]')
|
117
117
|
@args.shift # consumes the argument.
|
118
118
|
if @args.size <= 2
|
119
119
|
set_cmd(:knifeapps, :stop_applications, @args.size)
|
120
120
|
else
|
121
121
|
set_cmd(:knifeapps, :stop_applications, @args.size) # too many
|
122
122
|
end
|
123
|
-
when 'restart-applications'
|
124
|
-
usage('vmc_knife restart-
|
123
|
+
when 'restart-applications','restart-apps'
|
124
|
+
usage('vmc_knife restart-apps [<applications_regexp>]')
|
125
125
|
@args.shift # consumes the argument.
|
126
126
|
if @args.size <= 2
|
127
127
|
set_cmd(:knifeapps, :restart_applications, @args.size)
|
@@ -136,8 +136,56 @@ class VMC::Cli::KnifeRunner < VMC::Cli::Runner
|
|
136
136
|
else
|
137
137
|
set_cmd(:knifeapps, :delete_all, @args.size) # too many
|
138
138
|
end
|
139
|
+
when 'data-shell','psql','mongo'
|
140
|
+
usage('vmc_knife data-shell [<data-service-name>] [<app-name>]')
|
141
|
+
@args.shift # consumes the argument.
|
142
|
+
if @args.size <= 2
|
143
|
+
set_cmd(:knifeapps, :data_shell, @args.size)
|
144
|
+
else
|
145
|
+
set_cmd(:knifeapps, :data_shell, @args.size) # too many
|
146
|
+
end
|
147
|
+
when 'data-apply-privileges'
|
148
|
+
usage('vmc_knife data-apply-privileges [<data-service-name>] [<app-name>]')
|
149
|
+
@args.shift # consumes the argument.
|
150
|
+
if @args.size <= 2
|
151
|
+
set_cmd(:knifeapps, :data_apply_privileges, @args.size)
|
152
|
+
else
|
153
|
+
set_cmd(:knifeapps, :data_apply_privileges, @args.size) # too many
|
154
|
+
end
|
155
|
+
when 'data-credentials'
|
156
|
+
usage('vmc_knife data-credentials [<data-service-name>] [<app-name>]')
|
157
|
+
@args.shift # consumes the argument.
|
158
|
+
if @args.size <= 2
|
159
|
+
set_cmd(:knifeapps, :data_credentials, @args.size)
|
160
|
+
else
|
161
|
+
set_cmd(:knifeapps, :data_credentials, @args.size) # too many
|
162
|
+
end
|
163
|
+
when 'data-drop'
|
164
|
+
usage('vmc_knife data-drop [<data-service-name>] [<tables-collection-regexp>]')
|
165
|
+
@args.shift # consumes the argument.
|
166
|
+
if @args.size <= 3
|
167
|
+
set_cmd(:knifeapps, :data_drop, @args.size)
|
168
|
+
else
|
169
|
+
set_cmd(:knifeapps, :data_drop, @args.size) # too many
|
170
|
+
end
|
171
|
+
when 'data-import'
|
172
|
+
usage('vmc_knife data-import [<data-service-name>] [<tables-collection-regexp>]')
|
173
|
+
@args.shift # consumes the argument.
|
174
|
+
if @args.size <= 3
|
175
|
+
set_cmd(:knifeapps, :data_import, @args.size)
|
176
|
+
else
|
177
|
+
set_cmd(:knifeapps, :data_import, @args.size) # too many
|
178
|
+
end
|
179
|
+
when 'data-export'
|
180
|
+
usage('vmc_knife data-export [<data-service-name>] [<tables-collection-regexp>]')
|
181
|
+
@args.shift # consumes the argument.
|
182
|
+
if @args.size <= 3
|
183
|
+
set_cmd(:knifeapps, :data_export, @args.size)
|
184
|
+
else
|
185
|
+
set_cmd(:knifeapps, :data_export, @args.size) # too many
|
186
|
+
end
|
139
187
|
when 'help'
|
140
|
-
display "vmc_knife expand-manifest|login|start/stop/restart-
|
188
|
+
display "vmc_knife expand-manifest|login|start/stop/restart-apps|upload-apps|configure-all|configure-recipes|configure-apps|configure-services|delete-all|configure-vcap|configure-vcap-mdns|configure-vcap-etc-hosts|data-shell [<manifest_path>]"
|
141
189
|
else
|
142
190
|
super
|
143
191
|
end
|
@@ -65,7 +65,7 @@ module VMC::Cli::Command
|
|
65
65
|
man = load_manifest(nil)
|
66
66
|
uri = man['target']
|
67
67
|
end
|
68
|
-
update_aliases = VMC::KNIFE::VCAPUpdateAvahiAliases.new(nil,man,client)
|
68
|
+
update_aliases = VMC::KNIFE::VCAPUpdateAvahiAliases.new(nil,man,client,/.*/)
|
69
69
|
update_hosts = VMC::KNIFE::VCAPUpdateEtcHosts.new(uri,manifest_file_path,client)
|
70
70
|
update_hosts.set_all_uris(update_aliases.all_uris)
|
71
71
|
if update_hosts.update_pending()
|
@@ -76,7 +76,7 @@ module VMC::Cli::Command
|
|
76
76
|
# updates /etc/avahi/aliases
|
77
77
|
def configure_etc_avahi_aliases(etc_avahi_aliases=nil,manifest_file_path=nil)
|
78
78
|
man = load_manifest(manifest_file_path)
|
79
|
-
update_aliases = VMC::KNIFE::VCAPUpdateAvahiAliases.new(etc_avahi_aliases,man,client
|
79
|
+
update_aliases = VMC::KNIFE::VCAPUpdateAvahiAliases.new(etc_avahi_aliases,man,client)
|
80
80
|
update_aliases.do_exec = true
|
81
81
|
update_aliases.execute
|
82
82
|
end
|
@@ -187,6 +187,9 @@ module VMC::Cli::Command
|
|
187
187
|
# @param app_role_names The names of the apps in each recipe; nil: configure all apps found.
|
188
188
|
def configure(recipes_regexp=nil,app_names_regexp=nil,service_names_regexp=nil,manifest_file_path=nil)
|
189
189
|
man = load_manifest(manifest_file_path)
|
190
|
+
recipes_regexp = as_regexp(recipes_regexp)
|
191
|
+
app_names_regexp = as_regexp(app_names_regexp)
|
192
|
+
service_names_regexp = as_regexp(service_names_regexp)
|
190
193
|
configurer = VMC::KNIFE::RecipesConfigurationApplier.new(man,client,recipes_regexp,app_names_regexp,service_names_regexp)
|
191
194
|
if VMC::Cli::Config.trace
|
192
195
|
display "Pending updates"
|
@@ -196,28 +199,58 @@ module VMC::Cli::Command
|
|
196
199
|
end
|
197
200
|
|
198
201
|
def upload_applications(app_names_regexp=nil,manifest_file_path=nil)
|
199
|
-
recipe_configuror(:upload,nil,nil,
|
202
|
+
recipe_configuror(:upload,nil,app_names_regexp,nil,manifest_file_path)
|
200
203
|
end
|
201
204
|
def start_applications(app_names_regexp=nil,manifest_file_path=nil)
|
202
|
-
recipe_configuror(:start,nil,nil,
|
205
|
+
recipe_configuror(:start,nil,app_names_regexp,nil,manifest_file_path)
|
203
206
|
end
|
204
207
|
def stop_applications(app_names_regexp=nil,manifest_file_path=nil)
|
205
|
-
recipe_configuror(:stop,nil,nil,
|
208
|
+
recipe_configuror(:stop,nil,app_names_regexp,nil,manifest_file_path)
|
206
209
|
end
|
207
210
|
def restart_applications(app_names_regexp=nil,manifest_file_path=nil)
|
208
|
-
recipe_configuror(:restart,nil,nil,
|
211
|
+
recipe_configuror(:restart,nil,app_names_regexp,nil,manifest_file_path)
|
209
212
|
end
|
210
213
|
def delete_all(app_names_regexp=nil,manifest_file_path=nil)
|
211
|
-
recipe_configuror(:delete,nil,nil,
|
214
|
+
recipe_configuror(:delete,nil,app_names_regexp,nil,manifest_file_path)
|
215
|
+
end
|
216
|
+
def data_shell(data_names_regexp=nil,manifest_file_path=nil)
|
217
|
+
recipe_configuror(:shell,nil,nil,data_names_regexp,manifest_file_path)
|
218
|
+
end
|
219
|
+
def data_credentials(data_names_regexp=nil,manifest_file_path=nil)
|
220
|
+
recipe_configuror(:credentials,nil,nil,data_names_regexp,manifest_file_path)
|
221
|
+
end
|
222
|
+
def data_apply_privileges(data_names_regexp=nil,manifest_file_path=nil)
|
223
|
+
recipe_configuror(:apply_privileges,nil,nil,data_names_regexp,manifest_file_path)
|
224
|
+
end
|
225
|
+
def data_import(data_names_regexp=nil,app_name=nil,file_names=nil,manifest_file_path=nil)
|
226
|
+
recipe_configuror(:import,nil,nil,data_names_regexp,manifest_file_path,
|
227
|
+
{:file_names=>file_names, :app_name=>app_name})
|
228
|
+
end
|
229
|
+
def data_export(data_names_regexp=nil,app_name=nil,file_names=nil,manifest_file_path=nil)
|
230
|
+
recipe_configuror(:export,nil,nil,data_names_regexp,manifest_file_path,
|
231
|
+
{:file_names=>file_names, :app_name=>app_name})
|
232
|
+
end
|
233
|
+
def data_drop(data_names_regexp=nil,collection_or_table_names=nil,manifest_file_path=nil)
|
234
|
+
recipe_configuror(:drop,nil,nil,data_names_regexp,manifest_file_path,
|
235
|
+
{:collection_or_table_names=>collection_or_table_names})
|
212
236
|
end
|
213
237
|
|
214
|
-
def recipe_configuror(method_sym_name,recipes_regexp=nil,app_names_regexp=nil,service_names_regexp=nil,manifest_file_path=nil)
|
238
|
+
def recipe_configuror(method_sym_name,recipes_regexp=nil,app_names_regexp=nil,service_names_regexp=nil,manifest_file_path=nil,opts=nil)
|
215
239
|
man = load_manifest(manifest_file_path)
|
216
|
-
|
240
|
+
recipes_regexp = as_regexp(recipes_regexp)
|
241
|
+
app_names_regexp = as_regexp(app_names_regexp)
|
242
|
+
service_names_regexp = as_regexp(service_names_regexp)
|
243
|
+
configurer = VMC::KNIFE::RecipesConfigurationApplier.new(man,client,recipes_regexp,app_names_regexp,service_names_regexp,opts)
|
217
244
|
method_object = configurer.method(method_sym_name)
|
218
245
|
method_object.call
|
219
246
|
end
|
220
247
|
|
248
|
+
def as_regexp(arg)
|
249
|
+
if arg != nil && arg.kind_of?(String) && !arg.strip.empty?
|
250
|
+
Regexp.new(arg)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
221
254
|
end
|
222
255
|
|
223
256
|
end
|
@@ -0,0 +1,364 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require "interact"
|
3
|
+
require 'tempfile'
|
4
|
+
require 'tmpdir'
|
5
|
+
|
6
|
+
module VMC
|
7
|
+
module KNIFE
|
8
|
+
|
9
|
+
# returns only the result raw from psql
|
10
|
+
PSQL_RAW_RES_ARGS="-P format=unaligned -P footer=off -P tuples_only=on"
|
11
|
+
|
12
|
+
# Reads the cloud_controller config file for the connection parameters to ccdb.
|
13
|
+
def self.get_ccdb_credentials(ccdb_yml_path="#{ENV['HOME']}/cloudfoundry/config/cloud_controller.yml", db_type='production')
|
14
|
+
cc_conf = File.open( ccdb_yml_path ) do |yf| YAML::load( yf ) end
|
15
|
+
db = cc_conf['database_environment'][db_type]
|
16
|
+
db
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.get_postgresql_node_credentials(postgresql_node_yml_path="#{ENV['HOME']}/cloudfoundry/config/postgresql_node.yml")
|
20
|
+
db = File.open( postgresql_node_yml_path ) do |yf| YAML::load( yf ) end
|
21
|
+
db['postgresql']
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.get_app_id(app_name)
|
25
|
+
db=get_ccdb_credentials()
|
26
|
+
app_id = `psql --username #{db['username']} --dbname #{db['database']} -c \"select id from apps where name='#{app_name}'\" #{PSQL_RAW_RES_ARGS}`
|
27
|
+
app_id
|
28
|
+
end
|
29
|
+
def self.get_service_config_id(service_name)
|
30
|
+
db=get_ccdb_credentials()
|
31
|
+
#todo add the user_id
|
32
|
+
service_config_id = `psql --username #{db['username']} --dbname #{db['database']} -c \"select id from service_configs where alias='#{service_name}'\" #{PSQL_RAW_RES_ARGS}`
|
33
|
+
service_config_id
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a hash of the credentials for a data-service
|
37
|
+
# For example for postgres:
|
38
|
+
#---
|
39
|
+
#name: dc82ca85dfef740b7841211f354068beb
|
40
|
+
#host: 192.168.1.6
|
41
|
+
#hostname: 192.168.1.6
|
42
|
+
#port: 5432
|
43
|
+
#user: uafe612fbe7714af0ab04db22e199680d
|
44
|
+
#username: uafe612fbe7714af0ab04db22e199680d
|
45
|
+
#password: pd829916bfac34b3185e0f1158bf8920b
|
46
|
+
#node_id: postgresql_node_0
|
47
|
+
#
|
48
|
+
# For example for mongo:
|
49
|
+
#hostname: 192.168.0.103 +
|
50
|
+
#host: 192.168.0.103 +
|
51
|
+
#port: 25003 +
|
52
|
+
#name: 266401da-6853-4657-b212-814bd6f9d844 +
|
53
|
+
#db: db +
|
54
|
+
#username: c417f26c-6f49-4dd5-a208-216107279c7a+
|
55
|
+
#password: 8ab08355-6509-48d5-974f-27c853b842f5+
|
56
|
+
#node_id: mongodb_node_0
|
57
|
+
#
|
58
|
+
def self.get_credentials(service_name, app_name=nil)
|
59
|
+
db=get_ccdb_credentials()
|
60
|
+
if app_name.nil?
|
61
|
+
credentials_str = `psql --username #{db['username']} --dbname #{db['database']} -c \"select credentials from service_configs where alias='#{service_name}'\" #{PSQL_RAW_RES_ARGS}`
|
62
|
+
else
|
63
|
+
app_id = get_app_id(app_name)
|
64
|
+
service_config_id = get_service_config_id(service_name)
|
65
|
+
credentials_str = `psql --username #{db['username']} --dbname #{db['database']} -c \"select credentials from service_bindings where app_id = '#{app_id}' and service_config_id='#{service_config_id}'\" #{PSQL_RAW_RES_ARGS}`
|
66
|
+
end
|
67
|
+
res = Hash.new
|
68
|
+
credentials_str.split("\n").each do | line |
|
69
|
+
line =~ /([\w]*): ([\w|\.|-]*)$/
|
70
|
+
res[$1] = $2 if $2
|
71
|
+
end
|
72
|
+
res
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.pg_connect_cmd(credentials_hash, executable='psql',as_admin=false, other_params="")
|
76
|
+
if executable =~ /vacuumlo$/
|
77
|
+
# we don't have TEMP privilegeswhich are required by vacuumlo...
|
78
|
+
#"export PGPASSWORD=#{credentials_hash['password']}; #{executable} -h #{credentials_hash['hostname']} -p #{credentials_hash['port']} -U #{credentials_hash['username']} #{credentials_hash['name']}"
|
79
|
+
#workaround: use the superuser in the meantime:
|
80
|
+
db=get_postgresql_node_credentials()
|
81
|
+
db_arg = credentials_hash['name']
|
82
|
+
return "export PGPASSWORD=#{db['pass']}; #{executable} -h #{db['host']} -p #{db['port']} -U #{db['user']} #{other_params} #{db_arg}"
|
83
|
+
elsif executable =~ /pg_dump$/
|
84
|
+
db_arg = "#{other_params} #{credentials_hash['name']}"
|
85
|
+
else
|
86
|
+
#the other params are at the end
|
87
|
+
db_arg = "--dbname=#{credentials_hash['name']} #{other_params}"
|
88
|
+
end
|
89
|
+
if as_admin
|
90
|
+
# usually as vcap/vcap
|
91
|
+
db=get_postgresql_node_credentials()
|
92
|
+
"export PGPASSWORD=#{db['pass']}; #{executable} --host=#{db['host']} --port=#{db['port']} --username=#{db['user']} #{db_arg}"
|
93
|
+
else
|
94
|
+
"export PGPASSWORD=#{credentials_hash['password']}; #{executable} --host=#{credentials_hash['hostname']} --port=#{credentials_hash['port']} --username=#{credentials_hash['username']} #{db_arg}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# command_files or command.
|
99
|
+
def self.data_service_console(credentials_hash, commands_file="",as_admin=false)
|
100
|
+
if credentials_hash['db'] #so far it has always been equal to 'db'
|
101
|
+
# It is a mongo service
|
102
|
+
#/home/ubuntu/cloudfoundry/.deployments/intalio_devbox/deploy/mongodb/bin/mongo 127.0.0.1:25003/db
|
103
|
+
#-u c417f26c-6f49-4dd5-a208-216107279c7a -p 8ab08355-6509-48d5-974f-27c853b842f5
|
104
|
+
# Todo: compute the mongoshell path (?)
|
105
|
+
mongo_shell=find_mongo_exec()
|
106
|
+
cmd = "#{mongo_shell} -u #{credentials_hash['username']} -p #{credentials_hash['password']} #{credentials_hash['hostname']}:#{credentials_hash['port']}/#{credentials_hash['db']}"
|
107
|
+
puts "Executing #{cmd}"
|
108
|
+
if commands_file
|
109
|
+
if File.exists? commands_file
|
110
|
+
# not supported yet.
|
111
|
+
commands_file = "--eval \"#{`cat commands_file`}"
|
112
|
+
else
|
113
|
+
commands_file = "--eval \"#{commands_file}\""
|
114
|
+
end
|
115
|
+
`#{cmd} #{commands_file}`
|
116
|
+
else
|
117
|
+
# Replaces the current process.
|
118
|
+
exec cmd
|
119
|
+
end
|
120
|
+
else
|
121
|
+
cmd = pg_connect_cmd(credentials_hash, 'psql')
|
122
|
+
if commands_file
|
123
|
+
if File.exists? commands_file
|
124
|
+
commands_file = "-f #{commands_file} #{PSQL_RAW_RES_ARGS}"
|
125
|
+
else
|
126
|
+
commands_file = "-c \"#{commands_file}\" #{PSQL_RAW_RES_ARGS}"
|
127
|
+
end
|
128
|
+
`#{cmd} #{commands_file}`
|
129
|
+
else
|
130
|
+
# Replaces the current process.
|
131
|
+
exec cmd
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.find_mongo_exec()
|
137
|
+
mongo=`which mongo`
|
138
|
+
return mongo unless mongo.nil? || mongo.empty?
|
139
|
+
mongo_files = Dir.glob("#{ENV['HOME']}/cloudfoundry/.deployments/*/deploy/mongodb/bin/mongo")
|
140
|
+
mongo_files.first unless mongo_files.empty?
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.as_regexp(arg)
|
144
|
+
if arg != nil && arg.kind_of?(String) && !arg.strip.empty?
|
145
|
+
Regexp.new(arg)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class RecipesConfigurationApplier
|
150
|
+
def shell()
|
151
|
+
@data_services.each do |data_service|
|
152
|
+
app_name = opts()[:app_name] if opts()
|
153
|
+
data_service.shell(app_name)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
def credentials()
|
157
|
+
@data_services.each do |data_service|
|
158
|
+
data_service.credentials
|
159
|
+
end
|
160
|
+
end
|
161
|
+
def apply_privileges()
|
162
|
+
@data_services.each do |data_service|
|
163
|
+
data_service.apply_privileges
|
164
|
+
end
|
165
|
+
end
|
166
|
+
def import()
|
167
|
+
file_names = @opts[:file_names] if @opts
|
168
|
+
app_name = @opts[:app_name] if @opts
|
169
|
+
@data_services.each do |data_service|
|
170
|
+
data_service.import(app_name,file_names)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
def export()
|
174
|
+
file_names = opts()[:file_names] if opts()
|
175
|
+
app_name = opts()[:app_name] if opts()
|
176
|
+
@data_services.each do |data_service|
|
177
|
+
data_service.export(app_name,file_names)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
def drop()
|
181
|
+
collection_or_table_names = @opts[:collection_or_table_names] if @opts
|
182
|
+
@data_services.each do |data_service|
|
183
|
+
data_service.drop(collection_or_table_names)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
class DataService
|
190
|
+
include Interactive
|
191
|
+
|
192
|
+
# The credentials hash for this data-service
|
193
|
+
def credentials(app_name=nil)
|
194
|
+
#bound_app is the name of an app bound to the dat-service and that credentials
|
195
|
+
#should be used to access the data-service.
|
196
|
+
#for example if an app creates large objects you will need to use
|
197
|
+
#the credentials of that app to find the objects.
|
198
|
+
app_name ||= @wrapped['director']['bound_app'] if @wrapped['director']
|
199
|
+
@credentials ||= VMC::KNIFE.get_credentials(name(), app_name)
|
200
|
+
@credentials
|
201
|
+
end
|
202
|
+
|
203
|
+
# Connect to the mongo js shell or the psql shell.
|
204
|
+
def shell(commands_file=nil,as_admin=false)
|
205
|
+
VMC::KNIFE.data_service_console(credentials(),commands_file,as_admin)
|
206
|
+
end
|
207
|
+
|
208
|
+
def import(app_name=nil,file=nil)
|
209
|
+
file ||= @wrapped['director']['import_url'] if @wrapped['director']
|
210
|
+
if file.nil?
|
211
|
+
files = Dir.glob("#{name()}.*")
|
212
|
+
raise "Unable to locate the database file to import." if files.empty?
|
213
|
+
file = files.first
|
214
|
+
end
|
215
|
+
is_tmp = false
|
216
|
+
current_wd = Dir.pwd
|
217
|
+
begin
|
218
|
+
if file =~ /^https?:\/\// || file =~ /^ftp:\/\//
|
219
|
+
url = file
|
220
|
+
is_tmp = true
|
221
|
+
if file =~ /[^\/]*$/
|
222
|
+
basename = $0
|
223
|
+
end
|
224
|
+
tempfile = Tempfile.new("import_db_#{basename}")
|
225
|
+
wget_args = @application_json['repository']['wget_args']
|
226
|
+
if wget_args.nil?
|
227
|
+
wget_args_str = ""
|
228
|
+
elsif wget_args.kind_of? Array
|
229
|
+
wget_args_str = wget_args.join(' ')
|
230
|
+
elsif wget_args.kind_of? String
|
231
|
+
wget_args_str = wget_args
|
232
|
+
end
|
233
|
+
`wget #{wget_args_str} --output-document=#{tempfile.path} #{url}`
|
234
|
+
file = tempfile.path
|
235
|
+
end
|
236
|
+
#unzip if necessary (in progress)
|
237
|
+
|
238
|
+
if /\.tgz$/ =~ file || /\.tar\.gz$/ =~ file
|
239
|
+
tmp_dir = Dir.mktmpdir
|
240
|
+
Dir.chdir(tmp_dir.path)
|
241
|
+
`tar zxvf #{file.path}`
|
242
|
+
elsif /\.tar$/ =~ file
|
243
|
+
tmp_dir = Dir.mktmpdir
|
244
|
+
Dir.chdir(tmp_dir.path)
|
245
|
+
`tar xvf #{file}`
|
246
|
+
elsif /\.zip$/ =~ file
|
247
|
+
tmp_dir = Dir.mktmpdir
|
248
|
+
Dir.chdir(tmp_dir.path)
|
249
|
+
`unzip #{file}`
|
250
|
+
end
|
251
|
+
if tmp_dir
|
252
|
+
`rm #{file}`
|
253
|
+
files = Dir.glob("*.sql") if is_postgresql
|
254
|
+
files = Dir.glob("*.bson") if is_mongodb
|
255
|
+
files ||= Dir.glob("*")
|
256
|
+
raise "Can't find the db-dump file." if files.empty?
|
257
|
+
file = files.first
|
258
|
+
end
|
259
|
+
|
260
|
+
if is_postgresql
|
261
|
+
`chmod o+w #{file}`
|
262
|
+
#TODO:
|
263
|
+
if /\.sql$/ =~ file
|
264
|
+
other_params="--file #{file} --quiet"
|
265
|
+
cmd = VMC::KNIFE.pg_connect_cmd(credentials(app_name), 'psql',as_admin=false, other_params)
|
266
|
+
#`psql --dbname #{dbname} --file #{file} --clean --quiet --username #{rolename}`
|
267
|
+
else
|
268
|
+
other_params="--clean --no-acl --no-privileges --no-owner #{file}"
|
269
|
+
cmd = VMC::KNIFE.pg_connect_cmd(credentials(app_name), 'pg_restore',false, other_params)
|
270
|
+
#`pg_restore --dbname=#{dbname} --username=#{username} --no-acl --no-privileges --no-owner #{file}`
|
271
|
+
end
|
272
|
+
puts cmd
|
273
|
+
puts `#{cmd}`
|
274
|
+
`chmod o-w #{file}`
|
275
|
+
else
|
276
|
+
raise "Unsupported type of data-service. Postgresql is the only supported service at the moment."
|
277
|
+
end
|
278
|
+
ensure
|
279
|
+
file.unlink if is_tmp # deletes the temp file
|
280
|
+
tmp_dir.unlink if tmp_dir # deletes the temp directory
|
281
|
+
Dir.chdir(current_wd)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def export(app_name=nil,file=nil)
|
286
|
+
if is_postgresql
|
287
|
+
if file.nil?
|
288
|
+
extension = @wrapped['director']['file_extension'] if @wrapped['director']
|
289
|
+
extension = is_mongodb() ? "bson" : "sql"
|
290
|
+
file = "#{name()}.#{extension}"
|
291
|
+
end
|
292
|
+
`touch #{file}`
|
293
|
+
`chmod o+w #{file}`
|
294
|
+
puts "Exports the database #{credentials(app_name)['name']} in #{file}"
|
295
|
+
|
296
|
+
#sudo -u postgres env PGPASSWORD=$PGPASSWORD dbname=$DBNAME DUMPFILE=$DUMPFILE pg_dump --format=p --file=$DUMPFILE --no-owner --clean --blobs --no-acl --oid --no-tablespaces $DBNAME
|
297
|
+
|
298
|
+
cmd = VMC::KNIFE.pg_connect_cmd(credentials(app_name), 'pg_dump', false, "--format=p --file=#{file} --no-owner --clean --oids --blobs --no-acl --no-privileges --no-tablespaces")
|
299
|
+
puts cmd
|
300
|
+
puts `#{cmd}`
|
301
|
+
`chmod o-w #{file}`
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def is_postgresql()
|
306
|
+
credentials()['db'] == nil
|
307
|
+
end
|
308
|
+
|
309
|
+
def is_mongodb()
|
310
|
+
credentials()['db'] != nil
|
311
|
+
end
|
312
|
+
|
313
|
+
def apply_privileges()
|
314
|
+
if is_postgresql()
|
315
|
+
cmd_acl="GRANT CREATE ON SCHEMA PUBLIC TO PUBLIC;\
|
316
|
+
GRANT ALL ON ALL TABLES IN SCHEMA PUBLIC TO PUBLIC;\
|
317
|
+
GRANT ALL ON ALL FUNCTIONS IN SCHEMA PUBLIC TO PUBLIC;\
|
318
|
+
GRANT ALL ON ALL SEQUENCES IN SCHEMA PUBLIC TO PUBLIC;"
|
319
|
+
shell(cmd_acl,true)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def drop(collection_or_table_names=nil)
|
324
|
+
if is_postgresql
|
325
|
+
sel_tables = "SELECT table_name FROM information_schema.tables WHERE table_schema='public'"
|
326
|
+
if collection_or_table_names
|
327
|
+
sel_tables = "#{sel_tables} AND table_name LIKE '#{collection_or_table_names}'"
|
328
|
+
end
|
329
|
+
tables = shell(sel_tables)
|
330
|
+
tables_arr = Array.new
|
331
|
+
tables.split("\n").each do | line |
|
332
|
+
line.strip!
|
333
|
+
tables_arr << line if line
|
334
|
+
end
|
335
|
+
if tables_arr.size > 0 && ask("Delete the tables \"#{tables_arr.join(',')}\"?", :default => true)
|
336
|
+
#let's create a file in case there are a lot of tables:
|
337
|
+
file = Tempfile.new('droptables')
|
338
|
+
begin
|
339
|
+
File.open(file.path, 'w') do |f2|
|
340
|
+
tables_arr.each do |table|
|
341
|
+
f2.puts "DROP TABLE public.#{table} CASCADE;"
|
342
|
+
end
|
343
|
+
end
|
344
|
+
puts shell(file.path)
|
345
|
+
ensure
|
346
|
+
file.unlink # deletes the temp file
|
347
|
+
end
|
348
|
+
end
|
349
|
+
puts "Vacuum orphaned large objects..."
|
350
|
+
cmd = VMC::KNIFE.pg_connect_cmd(credentials(), 'vacuumlo')
|
351
|
+
puts cmd
|
352
|
+
puts `#{cmd}`
|
353
|
+
elsif is_mongodb
|
354
|
+
#TODO: iterate over the collections and drop them according to the filter.
|
355
|
+
raise "TODO: Unsupported operation 'drop' for the data-service #{name()}"
|
356
|
+
else
|
357
|
+
puts "Unsupported operation 'drop' for the data-service #{name()}"
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
end
|
data/lib/vmc_knife/vmc_knife.rb
CHANGED
@@ -197,12 +197,13 @@ module VMC
|
|
197
197
|
end
|
198
198
|
|
199
199
|
class RecipesConfigurationApplier
|
200
|
-
attr_accessor :root, :client, :applications, :recipes, :data_services
|
200
|
+
attr_accessor :root, :client, :applications, :recipes, :data_services, :opts
|
201
201
|
# Select the applications and data-services to configure according to the values
|
202
202
|
# in the SaaS manifest. When the selector is nil all of them are selected.
|
203
|
-
def initialize(manifest, client, recipe_sel=nil, application_sel=nil, service_sel=nil)
|
203
|
+
def initialize(manifest, client, recipe_sel=nil, application_sel=nil, service_sel=nil, opts=nil)
|
204
204
|
@root = Root.new manifest
|
205
205
|
@client = client
|
206
|
+
@opts=opts
|
206
207
|
@recipes = @root.recipes(recipe_sel)
|
207
208
|
@applications = Array.new
|
208
209
|
@data_services = Array.new
|
@@ -210,6 +211,14 @@ module VMC
|
|
210
211
|
@applications = @applications + recipe.applications(application_sel)
|
211
212
|
@data_services = @data_services + recipe.data_services(service_sel)
|
212
213
|
end
|
214
|
+
app_names = @applications.collect {|app| app.name }
|
215
|
+
service_names = @data_services.collect {|service| service.name }
|
216
|
+
if app_names.empty? && service_names.empty?
|
217
|
+
puts "No applications and data-services were selected."
|
218
|
+
else
|
219
|
+
puts "Applications selected #{app_names.join(', ')}" unless app_names.empty?
|
220
|
+
puts "Data-services selected #{service_names.join(', ')}" unless service_names.empty?
|
221
|
+
end
|
213
222
|
end
|
214
223
|
# Only for testing: inject json
|
215
224
|
def __set_current(current_services=nil,current_services_info=nil)
|
@@ -427,17 +436,38 @@ module VMC
|
|
427
436
|
if Dir.entries(Dir.pwd).size == 2
|
428
437
|
puts "Dir.entries(#{Dir.pwd}).size #{Dir.entries(Dir.pwd).size}"
|
429
438
|
#empty directory.
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
439
|
+
if /\.git$/ =~ url
|
440
|
+
`git clone #{url} --depth 1`
|
441
|
+
branch = @application_json['repository']['branch']
|
442
|
+
if branch
|
443
|
+
`git checkout #{branch}`
|
444
|
+
else
|
445
|
+
branch=master
|
446
|
+
end
|
447
|
+
`git pull origin #{branch}`
|
436
448
|
else
|
437
|
-
|
449
|
+
wget_args = @application_json['repository']['wget_args']
|
450
|
+
if wget_args.nil?
|
451
|
+
wget_args_str = ""
|
452
|
+
elsif wget_args.kind_of? Array
|
453
|
+
wget_args_str = wget_args.join(' ')
|
454
|
+
elsif wget_args.kind_of? String
|
455
|
+
wget_args_str = wget_args
|
456
|
+
end
|
457
|
+
`wget #{wget_args_str} --output-document=_download_.zip #{url}`
|
458
|
+
raise "Unable to download #{url}" unless $? == 0
|
459
|
+
if /\.tgz$/ =~ url || /\.tar\.gz$/ =~ url
|
460
|
+
`tar zxvf _download_.zip`
|
461
|
+
elsif /\.tar$/ =~ url
|
462
|
+
`tar xvf _download_.zip`
|
463
|
+
else
|
464
|
+
`unzip _download_.zip`
|
465
|
+
end
|
466
|
+
`rm _download_.zip`
|
438
467
|
end
|
439
|
-
`rm _download_.zip`
|
440
468
|
end
|
469
|
+
Dir.chdir(@application_json['repository']['sub_dir']) if @application_json['repository']['sub_dir']
|
470
|
+
`rm -rf .git` if File.exists? ".git"
|
441
471
|
VMC::KNIFE::HELPER.static_upload_app_bits(@client,@application_json['name'],Dir.pwd)
|
442
472
|
end
|
443
473
|
end
|
@@ -494,7 +524,7 @@ module VMC
|
|
494
524
|
updates = Hash.new
|
495
525
|
updates['name'] = name if name
|
496
526
|
updates['services'] = services if services
|
497
|
-
updates['env'] =
|
527
|
+
updates['env'] = env if env
|
498
528
|
updates['uris'] = uris if uris
|
499
529
|
updates['memory'] = memory if memory
|
500
530
|
updates unless updates.empty?
|
data/lib/vmc_knife.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vmc_knife
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 8
|
10
|
+
version: 0.0.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Intalio Pte
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-12-
|
18
|
+
date: 2011-12-12 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: vmc
|
@@ -106,6 +106,7 @@ files:
|
|
106
106
|
- lib/restclient/restclient_add_timeout.rb
|
107
107
|
- lib/vmc_knife/cli_extensions.rb
|
108
108
|
- lib/vmc_knife/commands/knife_cmds.rb
|
109
|
+
- lib/vmc_knife/data_services.rb
|
109
110
|
- lib/vmc_knife/json_expander.rb
|
110
111
|
- lib/vmc_knife/version.rb
|
111
112
|
- lib/vmc_knife/vmc_helper.rb
|