How To Create Google Compute Engine Instance Using Fog In Ruby - ruby

I try with following code but i am getting error,
server = connection.servers.create({
:name => "instance-#{Time.now}",
:image_name => "debian-7-wheezy-v20150325",
:machine_type => "f1-micro",
:zone_name => "us-central1-a",
})
/home/vijay/.rvm/gems/ruby-2.0.0-p598/gems/fog-core-1.30.0/lib/fog/core/attributes.rb:151:in `requires': disks is required for this operation (ArgumentError)
from /home/vijay/.rvm/gems/ruby-2.0.0-p598/gems/fog-1.29.0/lib/fog/google/models/compute/server.rb:218:in `save'
from /home/vijay/.rvm/gems/ruby-2.0.0-p598/gems/fog-core-1.30.0/lib/fog/core/collection.rb:51:in `create'
from google_compute_engine.rb:11:in `<main>'
I think i am missing some parameter which is required, can someone help me to solve this problem.

First create a disk:
disk = connection.disks.create({
:name => "my-disk",
:zone_name => "us-central1-a",
:size_gb => 10,
:source_image => "debian-7-wheezy-v20150325"})
Next create the instance with that disk:
server = connection.servers.create({
:name => "my-server",
:machine_type => "f1-micro",
:zone_name => "us-central1-a",
:disks => [disk.get_as_boot_disk]})
Note you can attach multiple disks at instance creation.

Related

Performance - Ruby - Compare large array of hashes (dictionary) to primary hash; update resulting value

I'm attempting to compare my data, which is in the format of an array of hashes, with another large array of hashes (~50K server names and tags) which serves as a dictionary. The dictionary is stripped down to only include the absolutely relevant information.
The code I have works but it is quite slow on this scale and I haven't been able to pinpoint why. I've done verbose printing to isolate the issue to a specific statement (tagged via comments below)--when it is commented out, the code runs ~30x faster.
After reviewing the code extensively, I feel like I'm doing something wrong and perhaps Array#select is not the appropriate method for this task. Thank you so much in advance for your help.
Code:
inventory = File.read('inventory_with_50k_names_and_associate_tag.csv')
# Since my CSV is headerless, I'm forcing manual headers
#dictionary_data = CSV.parse(inventory).map do |name|
Hash[ [:name, :tag].zip(name) ]
end
# ...
# API calls to my app to return an array of hashes is not shown (returns '#app_data')
# ...
#app_data.each do |issue|
# Extract base server name from FQDN (e.g. server_name1.sub.uk => server_name1)
derived_name = issue['name'].split('.').first
# THIS IS THE BLOCK OF CODE that slows down execution 30 fold:
#dictionary_data.select do |src_server|
issue['tag'] = src_server[:tag] if src_server[:asset_name].start_with?(derived_name)
end
end
Sample Data Returned from REST API (#app_data):
#app_data = [{'name' => 'server_name1.sub.emea', 'tag' => 'Europe', 'state' => 'Online'}
{'name' => 'server_name2.sub.us', 'tag' => 'US E.', 'state' => 'Online'}
{'name' => 'server_name3.sub.us', 'tag' => 'US W.', 'state' => 'Failover'}]
Sample Dictionary Hash Content:
#dictionary_data = [{:asset_name => 'server_name1-X98765432', :tag => 'Paris, France'}
{:asset_name => 'server_name2-Y45678920', :tag => 'New York, USA'}
{:asset_name => 'server_name3-Z34534224', :tag => 'Portland, USA'}]
Desired Output:
#app_data = [{'name' => 'server_name1', 'tag' => 'Paris, France', 'state' => 'Up'}
{'name' => 'server_name2', 'tag' => 'New York, USA', 'state' => 'Up'}
{'name' => 'server_name3', 'tag' => 'Portland, USA', 'state' => 'F.O'}]
Assuming "no" on both of my questions in the comments:
#!/usr/bin/env ruby
require 'csv'
#dictionary_data = CSV.open('dict_data.csv') { |csv|
Hash[csv.map { |name, tag| [name[/^.+(?=-\w+$)/], tag] }]
}
#app_data = [{'name' => 'server_name1.sub.emea', 'tag' => 'Europe', 'state' => 'Online'},
{'name' => 'server_name2.sub.us', 'tag' => 'US E.', 'state' => 'Online'},
{'name' => 'server_name3.sub.us', 'tag' => 'US W.', 'state' => 'Failover'}]
STATE_MAP = {
'Online' => 'Up',
'Failover' => 'F.O.'
}
#app_data = #app_data.map do |server|
name = server['name'][/^[^.]+/]
{
'name' => name,
'tag' => #dictionary_data[name],
'state' => STATE_MAP[server['state']],
}
end
p #app_data
# => [{"name"=>"server_name1", "tag"=>"Paris, France", "state"=>"Up"},
# {"name"=>"server_name2", "tag"=>"New York, USA", "state"=>"Up"},
# {"name"=>"server_name3", "tag"=>"Portland, USA", "state"=>"F.O."}]
EDIT: I find it more convenient here to read the CSV without headers, as I don't want it to generate an array of hashes. But to read a headerless CSV as if it had headers, you don't need to touch the data itself, as Ruby's CSV is quite powerful:
CSV.read('dict_data.csv', headers: %i(name tag)).map(&:to_hash)

What does a hash without a key mean in Ruby?

What does the {TOKEN} and {ACCOUNT_ID} mean in the following Ruby?
my_function({
:amount => 2000,
:currency => "usd",
:source => {TOKEN},
:destination => {ACCOUNT_ID}
})
I have Ruby 2.3.1 and am getting an error syntax error, unexpected '}', expecting => (SyntaxError)
A hash needs to be defined as either empty or with key, value pairs (see here). I'm guessing if you are following some sort of a tutorial, you need to fill those values in with some constants.
Usually variables in CAPS are constants, but it is possible to define a method in caps. Even so, one would need to call it explicitly with braces, as in TOKEN() and I can't think of anything that could be put inside curly braces to initialize a hash of some sort.
You probably need to end up with a structure like this:
my_function({
:amount => 2000,
:currency => "usd",
:source => "THE TOKEN",
:destination => "THE ACCOUNT ID"
})
or
my_function({
:amount => 2000,
:currency => "usd",
:source => "ckjnsdncc98n9dnx93d372n",
:destination => 123456
})
The {X} syntax looks like it's used as a placeholder for either Strings or numbers (most likely Strings)

Ruby docker-api to mount volume

How do I mount a host volume into docker with the ruby docker-api (https://github.com/swipely/docker-api) on runtime?
Basically, the docker run -v path:path functionality with this gem.
The current README missed the part to explain on how to use the volumes with container. You should be fine to run with below command with container's folder /foo
container = Docker::Container.create('Cmd' => %w[test -d /foo],
'Image' => 'debian:wheezy',
'Volumes' => {'/foo' => {}}
)
If you need mount with local folder, update to Volumes' => {'/foo' => '/local_foo'}
You can refer the test case from:
container_spec.rb
Documentation for docker-api gem states this in its README.md:
require 'docker'
# Create a Container.
container = Docker::Container.create('Cmd' => ['ls'], 'Image' => 'base')
# Attach to the Container. Currently, the below options are the only valid ones.
# By default, :stream, :stdout, and :stderr are set.
container.attach(:stream => true, :stdin => nil, :stdout => true, :stderr => true, :logs => true, :tty => false)
# => [["bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nselinux\nsrv\nsys\ntmp\nusr\nvar", []]
# If you wish to stream the attach method, a block may be supplied.
container = Docker::Container.create('Image' => 'base', 'Cmd' => ['find / -name *'])
container.tap(&:start).attach { |stream, chunk| puts "#{stream}: #{chunk}" }
stderr: 2013/10/30 17:16:24 Unable to locate find / -name *
# => [[], ["2013/10/30 17:16:24 Unable to locate find / -name *\n"]]
# If you want to attach to stdin of the container, supply an IO-like object:
container = Docker::Container.create('Image' => 'base', 'Cmd' => ['cat'], 'OpenStdin' => true, 'StdinOnce' => true)
container.tap(&:start).attach(stdin: StringIO.new("foo\nbar\n"))
# => [["foo\nbar\n"], []]
Does this help? Can I ask why are you trying to use docker-api? Can't you just use docker volumes (-v)?
Use Binds:
'Binds' => ['/local/folder:/container/folder']
You need to use both Marcelo's and BMW's answers together to create a container with a working volume:
container = Docker::Container.create('Cmd' => %w[test -d /foo],
'Image' => 'debian:wheezy',
'Volumes' => '/container' => {},
'Binds' => ['/local:/container']
)

Why is the mongo ruby driver adding a _id key to data hash after the first insert?

I am trying to insert this hash into my database:
a = {"name" => "Apple"}
So I connect using IRB.
irb(main):001:0> require 'mongo'
=> true
irb(main):002:0> include Mongo
=> Object
irb(main):003:0> client = MongoClient.new("localhost",27017).db("sample").collection("stack")
=> #<Mongo::Collection:0x9ee5c74 #name="stack", #db=#<Mongo::DB:0x9ee5ee0 #name="sample", #connection
Now this is where I run into an issue:
irb(main):004:0> client.count
=> 0
irb(main):005:0> a = {"name" => "Apples"}
=> {"name"=>"Apples"}
Works fine so far. Insert was successful.
> db.stack.find().pretty()
{ "_id" : ObjectId("525ee9d79fd1b325a4000001"), "name" : "Apples" }
Works on the ruby side:
irb(main):005:0> a = {"name" => "Apples"}
=> {"name"=>"Apples"}
irb(main):006:0> client.insert(a)
=> BSON::ObjectId('525ee9d79fd1b325a4000001')
Here is where the error occurs, if I try to add the same hash again
irb(main):007:0> client.insert(a)
Mongo::OperationFailure: 11000: E11000 duplicate key error index: sample.stack.$_id_ dup key: { : ObjectId('525ee9d79fd1b325a4000001') }
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/networking.rb:103:in `send_message_with_gle'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/collection.rb:1121:in `block in send_insert_message'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/util/logging.rb:55:in `block in instrument'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/util/logging.rb:20:in `instrument'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/util/logging.rb:54:in `instrument'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/collection.rb:1119:in `send_insert_message'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/collection.rb:1111:in `insert_batch'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/collection.rb:1169:in `insert_documents'
from /var/lib/gems/1.9.1/gems/mongo-1.9.2/lib/mongo/collection.rb:389:in `insert'
from (irb):7
from /usr/bin/irb:12:in `<main>'
What? My Hash has changed
irb(main):008:0> a
=> {"name"=>"Apples", :_id=>BSON::ObjectId('525ee9d79fd1b325a4000001')}
_id field has been added to it, so how will I handle batch Inserts if this is the way its going to be done?
Why is there default behavior to add the _id to my original hash, and how do I get around it
After some searching, it seems this is behaviour in the BSON Gem.
[http://api.mongodb.org/ruby/current/BSON/ObjectId.html][1]
+ (BSON::ObjectId, Object) create_pk(doc)
File 'lib/bson/types/object_id.rb', line 91
def self.create_pk(doc)
doc.has_key?(:_id) || doc.has_key?('_id') ? doc : doc.merge!(:_id => self.new)
end
How would a person so things like:
a = {"name" => "Blue"}
2.times {client.insert(a)}
If you really don't want it adding an ID, maybe just dup the object when you insert it?
a = { "name" => "Blue" }
2.times { client.insert(a.dup) }

rake import- only adding one line from csv to database

I am attempting to import a CSV file into my rails database (SQLite in Development) following this tutorial. Data is actually getting inserted into my database but it seems to only insert the first record from the CSV File. the rake seems to run without problem. and a running it with --trace reveals no additional information.
require 'csv'
desc "Import Voters from CSV File"
task :import => [:environment] do
file = "db/GOTV.csv"
CSV.foreach(file, :headers => false) do |row|
Voter.create({
:last_name => row[0],
:first_name => row[1],
:middle_name => row[2],
:name_suffix => row[3],
:primary_address => row[4],
:primary_city => row[5],
:primary_state => row[6],
:primary_zip => row[7],
:primary_zip4 => row[8],
:primary_unit => row[9],
:primary_unit_number => row[10],
:phone_number => row[11],
:phone_code => row[12],
:gender => row[13],
:party_code => row[14],
:voter_score => row[15],
:congressional_district => row[16],
:house_district => row[17],
:senate_district => row[18],
:county_name => row[19],
:voter_key => row[20],
:household_id => row[21],
:client_id => row[22],
:state_voter_id => row[23]
})
end
end
Just ran into this as well - guess you solved it some other way, but still might be useful for others.
In my case, the issue seems to be an incompatible change in the CSV library.
I guess you were using Ruby 1.8, where
CSV.foreach(path, rs = nil, &block)
The docs here are severely lacking, actually no docs at all, so have to guess from source: http://ruby-doc.org/stdlib-1.8.7/libdoc/csv/rdoc/CSV.html#method-c-foreach..
Anyway, 'rs' is clearly not an option hash, it looks like the record separator.
In Ruby 1.9 this is nicer: http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html#method-c-foreach
self.foreach(path, options = Hash.new, &block)
so this is the one that supports options such as :headers..

Resources