vmc_knife 0.0.7 → 0.0.8
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.
- 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
|