I want to get the recipes that a cookbook contains, through chef-server-api. Following is the code I'm using for getting the cookbook list, individual cookbook details through the api :
require 'rubygems'
require 'chef/config'
require 'chef/log'
require 'chef/rest'
require 'chef/cookbook_version'
client_name = "admin"
signing_key_filename="c:/chef-repo/.chef/admin.pem"
server_url = "https://10.132.17.244:443"
rest = Chef::REST.new(server_url, client_name, signing_key_filename)
cookbooks = rest.get_rest("/cookbooks?all_versions")
cookbooks.keys.each do |name|
cookbook_versions = rest.get_rest("/cookbooks/#{name}")
print "#{name}\n"
cookbook_versions[name]["versions"].each do |cv|
version = cv["version"]
cookbook = rest.get_rest("/cookbooks/#{name}/#{version}")
print "\t#{cookbook}\n"
#parsed = JSON[cookbook]
end
end
The problem I'm facing is to get the recipe list from the 'cookbook' object. I tried parsing it to ruby hash and then read, but of no use. If I directly print the 'cookbook' variable, the output is something like the screenshot
I'm not able to get how to interpret the output I am getting by hitting the '/cookbooks/NAMEW/VERSION' endpoint, and get the recipes present in an individual cookbooks.
When using the Chef gem it automatically decodes some responses into Ruby objects for you. You can either use the object directly (specifically you want #recipe_filenames and then parse those to the cookbook_name::recipe_name format) or you could use a better API client like Chef-API or PyChef.
Need a ruby solution? The following example uses jq to filter the JSON resultset returned by knife:
$ knife cookbook show apache2 2.0.0 recipes -Fj | jq '.[]|.name'
"mod_cgi.rb"
"mod_proxy_http.rb"
"mod_proxy_html.rb"
"mod_access_compat.rb"
"mod_authz_dbd.rb"
"mod_proxy_express.rb"
..
..
Related
New to Chef, bare wi/ me. Building my cookbook.
How did you set the databag?
are you able to get the credential out using :
$ knife vault show nameOfVault nameOfItem
or
$ knife data bag show nameOfVault nameOfItem_keys
Glad you have your data bag loading and indeed, with Test Kitchen you do not need to use knife to upload to Chef Server, as Test Kitchen uses Chef Zero / Solo.
The issue you have here is that you have not correctly formatted reading from the data bag object once you have read. You need to do this instead:
ruby_block "insert_line" do
block do
file = Chef::Util::FileEdit.new('/var/lib/net-snmp/snmpd.conf')
file.insert_line_if_no_match("/www.example.com/", "createUser
#{snmp3usercreds['user']}
SHA #{snmp3usercreds['auth_pssword']}
AES #{snmp3usercreds['enc_password']} ")
file.write_file
end
end
So, you will see I have changed snmp3usercreds[user] to snmp3usercreds['user'] with quotes around the user to show it is a string (rather than a variable as is the case with your code).
I'm trying to remove the following bash command from my ruby script:
nodes = "knife search 'chef_environment:#{env} AND recipe:#{microservice}' -i 2>&1 | tail -n 2"
node = %x[ #{nodes} ].split
node.each do |n|
puts n
end
And replace it with something like this:
node = Chef::Knife.search("chef_environment:#{env} AND recipe:#{microservice}").split
Is this possible? Is there any documentation regarding Chef::knife library in ruby and how to use it?
To access a chef server, you could try to use the ridley gem, which is also used by Berkshelf and thus generally up-to-date.
A usage example could be:
ridley = Ridley.from_chef_config('/path/to/knife.rb')
ridley.search(:node, "chef_environment:#{env} AND recipe:#{microservice}")
See the documentation of the gem for a more detailed description of its options.
I am doing data scraping with Ruby and Nokogiri. Is it possible to download and parse a local file in my computer?
I have:
require 'open-uri'
url = "file:///home/nav/Desktop/Scraping/scrap1.html"
It gives error as:
No such file or directory # rb_sysopen - file:\home/nav/Desktop/Scraping/scrap1.html
If you want to parse a local file with Nokogiri you can do it like this.
file = File.read('/home/nav/Desktop/Scraping/scrap1.html')
doc = Nokogiri::HTML(file)
When you open a local file in a browser, the URL in the address bar is displayed as:
file:///Users/7stud/Desktop/accounts.txt
But that doesn't mean you use that format in a Ruby script. Your Ruby script doesn't send the file name to a browser and then ask the browser to retrieve the file. Your Ruby script searches your file system directly.
The same is true for URLs: your Ruby script doesn't ask your browser to go retrieve a page from the internet, Ruby retrieves the page itself by sending a request using your system's network interface. After all, a browser and a Ruby program are both just computer programs. What your browser can do over a network, a Ruby program can do, too.
This works for me:
require 'open-uri'
text = open('./data.txt').read
puts text
You have to get your path right, though. The only reason I can think of to use open() is if you had an array of filenames and URLs mixed together. If that isn't your situation, see new2code's answer.
This is how I do it as according to the documentation.
f = File.open("//home/nav/Desktop/Scraping/scrap1.html")
doc = Nokogiri::HTML(f)
f.close
I would make use of Mechanize and save the file locally, then parse it with Nokogiri like so:
# Save the file
agent = Mechanize.new
agent.pluggable_parser.default = Mechanize::Download
current_url = 'http://www.example.com'
file = agent.get(current_url)
file.save!("#{Rails.root}/tmp/")
# Read the file
page = Nokogiri::HTML::Reader(File.open(file))
Hope that helps!
Ubuntu 12.04
Sinatra 1.3.3
Why does passing an argument to a ruby system call (%x[] or ``) give me a 'not found' error in my sinatra app? The same code works fine in a normal ruby script running from the same directory.
I have a file test.rb like this
output = %x["ls"]
p output
When I run it with "ruby test.rb" I get the contents of the current directory in the console, as expected.
If I modify the program to give an argument to the system call like so:
output = %x["ls sub_dir/"]
p output
I get the contents of sub_dir, which sits in the current directory, as expected.
So far so good.
Now if I make a Sintra app with a post method:
require 'rubygems'
require 'bundler/setup'
require 'sinatra'
post "/" do
output = x["ls"]
return output
end
The response to a Post call to "/" returns the contents of the current directory, which includes 'sub_dir', as expected.
If I try to add the argument to the system call to the sinatra app like so:
require 'rubygems'
require 'bundler/setup'
require 'sinatra'
post "/" do
output = x["ls sub_dir/"]
return output
end
the response is nil and there is an error in the console:
sh: 1: ls sub_dir/: not found
Why does adding a parameter to a system call in my sinatra app cause it to crash, when the same code called from a plain ruby script, run from the same location works perfectly.
By the way, the 'ls' example shown here is not the command I really need to run, so please don't explain a different way to get this information. I have an executable file that takes a file name as a parameter that I need to run, which behaves exactly the same way.
Thanks in advance!
If you want to specify a path in relation to the application, you could use something like this:
post "/" do
path = File.join(File.dirname(__FILE__), "sub_dir")
%x[ls #{path}]
end
However, if you want to list the contents of a directory, why not do it in Ruby?
I rewrote the sinatra app in another file in the same directory.
Everything works as expected.
I did not find the reason and I deleted the original file so that I won't lose anymore time trying to figure it out.
Something along the lines of:
def domain_exists?(domain)
# perform check
# return true|false
end
puts "valid!" if domain_exists?("example.com")
require 'socket'
def domain_exists?(domain)
begin
Socket.gethostbyname(domain)
rescue SocketError
return false
end
true
end
If you want to check whether a domain is registered or not, then you need to perform a Whois query.
http://www.ruby-whois.org/
With ruby-whois is pretty easy:
Install gem and require.
a = Whois.whois("google.com")
a.available?
=> false
There is also a CLI bundled if you install it via ruby gems: ruby-whois
web page at: ruby-whois.org
You could shell out to nslookup like this:
`nslookup #{domain}`
and parse the results as text with regexes etc.
Or you can use the Socket class, specifically Socket.getaddrinfo. See previous StackOverflow answer on this very question.