How to create a config file for multiple environments in Ruby? - ruby

I don't want to confuse you so what I want to do is the following:
I have three environments:
www.env1.com
www.env2.com
www.env3.com
I want to create something to define the setup phase according the environment over which I want to run the scripts, that is:
Current set-up:
def setup
#verification_errors = []
#selenium = Selenium::Client::Driver.new(
:host => "localhost",
:port => 4444,
:browser => "*firefox C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe",
:url => "www.env1.com",
:timeout_in_second => 60
)
#selenium.start_new_browser_session
end
What I want:
def setup
#verification_errors = []
#selenium = Selenium::Client::Driver.new(
:host => "localhost",
:port => 4444,
:browser => "*firefox C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe",
**:url => This parameter configurable from a file or other source.**
:timeout_in_second => 60
)
#selenium.start_new_browser_session
end
If this is possible I can switch environments without having to re-write all test cases.
Hope you can help me out, I really need to do this.

YAML is a great data serialization language for handling configuration information. It comes with Ruby so you only have to do:
require 'yaml'
to load it in, then something like:
configuration = YAML::load_file('path/to/yamldata.yaml')
All your configuration data will be available inside the configuration variable.
Generally I create a stub for my YAML files by writing some Ruby code, defining the configuration hash that contains it, then telling YAML to generate the file for me. See the docs for load_file and dump for ways to do that.
For something like you're doing I'd create a hash like:
configuration = {
'env1' => "www.env1.com",
'env2' => "www.env2.com",
'env3' => "www.env3.com",
}
Using YAML::dump(configuration) returns:
---
env1: www.env1.com
env2: www.env2.com
env3: www.env3.com
which you'd want to write to your .yaml file, then load later at run-time and access it like:
#selenium = Selenium::Client::Driver.new(
:host => "localhost",
:port => 4444,
:browser => "*firefox C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe",
:timeout_in_second => 60
:url => configuration['env1'],
)
You can replace 'env1' with the other keys to use env2 or env3.
Rails uses YAML to make one file handle the development, test and production information for an application. At work I use it to do similar things, where one file contains our development and production environmental information for apps, plus the definitions of some hashes we need to maintain, but don't want to have to modify the code to do so.

Related

Upload file to server and delete original using NET::SCP gem in Ruby

I'm using the net/scp gem to upload a file from my machine to a remote Linux server.
require 'net/ssh'
require 'net/scp'
Net::SCP.upload!(10.125.0.0,
user,
local_path,
remote_dir,
:ssh => { :password => psw,
:key_data => keys})
This works perfectly, however I'd like to be able to 'move' the file instead of effectively copying it across.
Is there some scpparameter that will delete the original file?
Net::SCP doesn't have any such parameter:
https://github.com/net-ssh/net-scp/blob/master/lib/net/scp.rb#L259-L267
Since the only difference between a copy and a move is just a final deletion of the source, you should do this manually after upload!.
File.delete(local_path)
You most likely will want to make sure that Net::SCP has finished before doing so:
require 'net/ssh'
require 'net/scp'
channel = Net::SCP.upload!(10.125.0.0,
user,
local_path,
remote_dir,
:ssh => { :password => psw,
:key_data => keys})
channel.wait
File.delete(local_path)

compass/sass remote themeing via sftp/scp with alternate port

I am trying to get compass/sass to watch changes on my local computer and reflect those changes remotely using a custom config.rb script. net::sftp works but my server requires a custom ssh port. I couldn't find any mods to make sftp work with an alternate port so im trying net:scp now, the problem is I dont know the proper command structure to upload using net:scp and wanted to see if someone can help me. Here is my code:
# Require any additional compass plugins here.
require 'net/ssh'
require 'net/scp'
# SFTP Connection Details - Does not support alternate ports os SSHKeys, but could with mods
remote_theme_dir_absolute = '/home2/trinsic/public_html/scottrlarson.com/sites/all/themes/ gateway_symbology_zen/css'
sftp_host = 'xxx.xxx.xxx.xxx' # Can be an IP
sftp_user = 'user' # SFTP Username
sftp_pass = 'password' # SFTP Password
# Callback to be used when a file change is written. This will upload to a remote WP install
on_stylesheet_saved do |filename|
$local_path_to_css_file = css_dir + '/' + File.basename(filename)
Net::SSH.start( sftp_host, sftp_user, {:password => sftp_pass,:port => 2222} ) do ssh.scp.upload! $local_path_to_css_file, remote_theme_dir_absolute + '/' + File.basename(filename)
end
puts ">>>> Compass is polling for changes. Press Ctrl-C to Stop"
end
#
# This file is only needed for Compass/Sass integration. If you are not using
# Compass, you may safely ignore or delete this file.
#
# If you'd like to learn more about Sass and Compass, see the sass/README.txt
# file for more information.
#
# Change this to :production when ready to deploy the CSS to the live server.
environment = :development
#environment = :production
# In development, we can turn on the FireSass-compatible debug_info.
firesass = false
#firesass = true
# Location of the theme's resources.
css_dir = "css"
sass_dir = "sass"
extensions_dir = "sass-extensions"
images_dir = "images"
javascripts_dir = "js"
# Require any additional compass plugins installed on your system.
#require 'ninesixty'
#require 'zen-grids'
# Assuming this theme is in sites/*/themes/THEMENAME, you can add the partials
# included with a module by uncommenting and modifying one of the lines below:
#add_import_path "../../../default/modules/FOO"
#add_import_path "../../../all/modules/FOO"
#add_import_path "../../../../modules/FOO"
##
## You probably don't need to edit anything below this.
##
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
output_style = (environment == :development) ? :expanded : :compressed
# To enable relative paths to assets via compass helper functions. Since Drupal
# themes can be installed in multiple locations, we don't need to worry about
# the absolute path to the theme from the server root.
relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
# Pass options to sass. For development, we turn on the FireSass-compatible
# debug_info if the firesass config variable above is true.
sass_options = (environment == :development && firesass == true) ? {:debug_info => true} : {}
I get an error when I run the command: compass watch:
NoMethodError on line ["17"] of K: undefined method `upload!' for #<Net::SSH::Co
nnection::Session:0x000000036bb220>
Run with --trace to see the full backtrace
I needed a solution for this too but did not find any satisfying answer anywhere.
After reading the Ruby Net::ssh documentation and some source of Compass, this is my solution to upload CSS and sourcemap to a remote SSH server with non-standard port and forced public-key authorisation:
First make sure you have the required gems installed
sudo gem install net-ssh net-sftp
then add this to your config.rb
# Add this to the first lines of your config.rb
require 'net/ssh'
require 'net/sftp'
...
# Your normal compass config comes here
...
# At the end of your config.rb add the config for the upload code
remote_theme_dir_absolute = '/path/to/my/remote/stylesheets'
sftp_host = 'ssh_host' # Can be an IP
sftp_user = 'ssh_user' # SFTP Username
on_stylesheet_saved do |filename|
# You can use the ssh-agent for authorisation.
# In this case you can remove the :passphrase from the config and set :use_agent => true.
Net::SFTP.start(
sftp_host,
sftp_user ,
:port => 10022,
:keys_only => true,
:keys => ['/path/to/my/private/id_rsa'],
:auth_methods => ['publickey'],
:passphrase => 'my_secret_passphrase',
:use_agent => false,
:verbose => :warn
) do |sftp|
puts sftp.upload! css_dir + '/app.css', remote_theme_dir_absolute + '/' + 'app.css'
end
end
on_sourcemap_saved do |filename|
# You can use the ssh-agent for authorisation.
# In this case you can remove the :passphrase from the config and set :use_agent true.
Net::SFTP.start(
sftp_host,
sftp_user ,
:port => 10022,
:keys_only => true,
:keys => ['/path/to/my/private/id_rsa'],
:auth_methods => ['publickey'],
:passphrase => 'my_secret_passphrase',
:use_agent => false,
:verbose => :warn
) do |sftp|
puts sftp.upload! css_dir + '/app.css.map', remote_theme_dir_absolute + '/' + 'app.css.map'
end
end
It was quite some trial and error until this worked for me.
Some points of failure were:
If no ssh-agent is available connection will fail until you set :ssh_agent => false explicitly
If you do not limit the available keys with :keys all available keys will be tried one after another. If you use the ssh-agent and have more than 3 keys installed chanches are high that the remote server will close the connection if you try too much keys that are not valid for the server you currently connect.
On any connection issue set verbosity level to :verbose => :debug to see what is going on. Remember to stop the compass watch and restart to ensure configuration changes apply.

Get Postgres-activerecord setup to work both locally and in Heroku

I'm automating DB creation (with a Rakefile in a Sinatra App).
I would like to be able to run the rakefile from my Linux user "pete" (eg pete#pete_laptop: /path $ rake db:create) AND from Heroku.
It comes down to the settings in my config/database.rb:
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:port => db.port,
# pete#ubuntu_14.04_laptop--------
# :username => 'pete',
# :password => 'password',
# OR
# heroku -----------------
# :username => db.user,
# :password => db.password,
:database => DB_NAME,
:encoding => 'utf8'
)
If I use the pete#ubuntu_laptop settings, the database works in localhost but not in Heroku,
If I use the heroku settings, the database works in localhost but not in Heroku.
How can I setup this file/my ubuntu laptop so that the app works both on localhost & in Heroku?
Cheers,
Pete
You can use environment variables which can be accessed like ENV["PG_USER"] in Ruby. If you want to use it in a yml file you can put it in erb tags <%= ENV["PG_USER"] %> and render it with erb before passing it to your config.
You can set environment variables in your .bashrc or you can use something like the dotenv gem. On heroku you can set environment variables like heroku config:set PG_USER=postgres.
But check whether this is really necessary for heroku. In Rails, for instance, heroku provides a database configuration, so there is no need to configure it.
oK! With help got it working!
used:
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:port => db.port,
:username => ENV['PG_USER'] || db.user,
:password => ENV['PG_PASSWORD'] || db.password,
:database => DB_NAME,
:encoding => 'utf8'
)
AND
added this to my shell-rc (in my case ~/.zshrc)
export PG_USER='pete'
export PG_PASSWORD='password'
now in my local environment the username & password pick up the ENV['PG...] variables from the terminal I launch the app in.
Note: 'export' is important - without it the variables don't get sent to the app's 'ENV'

In Ruby, how to upload multiple files in single request using RESTClient

I have to upload multiple files as form request. I am using the Rest Client to post my request. I am able to upload single file but I am not sure how to add multiple files in a single request.
I searched/googled for such option and I am not finding any solution that solves my problem.
Below is my code.
It has variable argument (*yamlfile) which takes one or more files. I have to upload all the files together.
The issue now is , I am getting syntax error when I add the loop to extract the file within the payload.
my assumption is now to form this outside the payload and include it inside the payload block but I am not sure how to do it.
Can someone help me with that.
( I have tried net/http/post/multipart library too and I don't find much documents around it)
def uploadRest(endpoint,archive_file_path,,yaml_file_path,*yamlfile)
$arg_len=yamlfile.length
request = RestClient::Request.new(
:method => :post,
:url => endpoint,
:payload => {
:multipart => true,
:job_upload_archive => File.new(archive_file_path,'rb'),
:job_upload_path => "/tmp",
# Trying to add multiple file, but I get syntax error
yamlfile.each_with_index { |yaml, index|
:job_upload_yaml_file+index => File.new("#{yaml_file_path}/#{pmml}")
}
})
response=request.execute
puts response.code
end
uploadRest(endpoint,archive_file_path,yaml_file_path,*yamlfile)
#files=Array.new
yamlfile.each{ |yaml_file|
#files.push(File.new("#{yaml_file_path}/#{yaml_file}"))
}
request = RestClient::Request.new(
:method => :post,
:url => endpoint,
:payload => { :multipart => true, :job_upload_archive => File.new(archive_file_path,'rb'),
:job_upload_path => "/tmp", :job_upload_yaml_file => #files })
response=request.execute
end
I had a similar problem and was able to get this to work by passing an array of arrays as a requests.
file1 = File.new("#{yaml_file_path}/#{yaml_file1}", 'rb')
file2 = File.new("#{yaml_file_path}/#{yaml_file}", 'rb')
request_body = [["files", file1], ["files", file2]]
RestClient.post url, request_body, request_headers
There were two issues with your question code:
1) Attempt to add a symbol to an integer
2) Attempt to insert contents of yamlfile direct into the hash (because that is what yamlfile.each_with_index returns, as opposed to how it calls your block. The return value from the block is not used)
Both of these code issues read as if you have gained experience in HAML or another templating language, and are using structures/ideas that would work in that?
There are lots of possble solutions in Ruby, but a simple approach to build up the hash in parts, as opposed to generate it in one go with clever hash-returning routines embedded. Try something like this:
payload_hash = {
:multipart => true,
:job_upload_archive => File.new(archive_file_path,'rb'),
:job_upload_path => "/tmp",
}
# This does not use the return value from each_with_index, instead it relies
# on the block to make changes to the hash by adding new key/value pairs
yamlfile.each_with_index { |yaml, index|
# This concatenates two strings, and then converts the combined
# string into the symbol that you want
file_key = ("job_upload_yaml_file"+index.to_s).to_sym
payload_hash[file_key] = File.new("#{yaml_file_path}/#{yaml}")
}
request = RestClient::Request.new(
:method => :post,
:url => endpoint,
:payload => payload_hash
)
For added code cleanliness, you could make the first two parts a separate method, and call it where it currently has payload_hash.
This should get you over current syntax hurdles. However, I have made no attempt to check whether this will allow you to upload multiple files via RESTClient.
Section1:
#params = {
"FacialImage" => UploadIO.new(File.new('C:\temp\ATDD\Test\test\sachin.jpg'), "image/jpeg"),
"Login" => UploadIO.new(File.new('C:\temp\ATDD\Test\test\login.txt'), "application/json")
}

Is there any way to get resque-web to work with Redis To Go hosted redis instance?

Is there any way to get resque-web to work with a Redis To Go hosted redis instance?
UPDATE:
#Nemo157's suggestion was correct. Ended up creating a test-evn.rb containing:
uri = URI.parse(" redis://XXXX#catfish.redistogo.com:9122")
Resque.redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
Pass it the config file you're using to setup redis in the app, e.g.
resque-web ./environment.rb
where environment.rb contains something like:
Resque.redis = Redis.new(:host => "path.to.host", :port => 6379)
Note: I haven't tested this since all my redis instances have been on localhost, but that's my understanding of how it works.

Resources