I intend to create an AWS lambda function using Ruby 2.7 with Selenium. When I try to run my example function i get:
{
"errorMessage": "unable to connect to /opt/chromedriver 127.0.0.1:9515",
"errorType": "Function<Selenium::WebDriver::Error::WebDriverError>",
"stackTrace": [
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/common/service_manager.rb:138:in `connect_until_stable'",
Which is confusing to me because the file is located in that path. I have created a AWS layer with both chromedriver and chromium headless. After creating the layers i have attached them to the function. The error when the files are not there is different so I am assuming it can reach the files.
My sample program is:
require 'json'
require 'selenium-webdriver'
def lambda_handler(event:, context:)
driver = setup_driver
driver.navigate.to 'http://www.google.com'
element = driver.find_element(name: 'q')
element.send_keys 'Pizza'
element.submit
title = driver.title
driver.quit
{ statusCode: 200, body: JSON.generate(title) }
end
def setup_driver
service = Selenium::WebDriver::Service.chrome(path: '/opt/chromedriver')
Selenium::WebDriver.for :chrome, service: service, options: driver_options
end
def driver_options
options = Selenium::WebDriver::Chrome::Options.new(binary: '/opt/headless-chromium')
options.add_argument('--no-sandbox')
options.add_argument('--headless')
options.add_argument("--window-size=#{800},#{600}")
options.add_argument('--disable-popup-blocking')
options.add_argument('--disable-gpu')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--single-process')
return options
end
Update:
After locating the proper chromedriver and installing google chrome from the yum repo i managed to get it to work locally.
Here is my Dockerfile
FROM public.ecr.aws/lambda/ruby:2.7
COPY . ${LAMBDA_TASK_ROOT}
RUN bundle config --local silence_root_warning true
RUN bundle install --path vendor/bundle --clean
# USER root
RUN yum -y install wget unzip
# Chromium
COPY google-chrome.repo /etc/yum.repos.d/google-chrome.repo
RUN yum install google-chrome-stable -y
# Chromedriver
RUN wget https://chromedriver.storage.googleapis.com/102.0.5005.61/chromedriver_linux64.zip
RUN unzip chromedriver_linux64.zip -d /usr/bin/
RUN rm chromedriver_linux64.zip
CMD [ "lambda_function.lambda_handler" ]
When i run it locally with:
docker run -p 9000:8080 prueba
And test it in a different terminal:
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
{"statusCode":200,"body":"\"Pizza - Buscar con Google\""}%
It works wonderful!!!
However when deploying it (By publishing the docker image in the ECR and creating a lambda using given docker image) i get the following error:
{
"errorMessage": "Net::ReadTimeout with #<TCPSocket:(closed)>",
"errorType": "Function<Net::ReadTimeout>",
"stackTrace": [
"/var/lang/lib/ruby/2.7.0/net/protocol.rb:217:in `rbuf_fill'",
"/var/lang/lib/ruby/2.7.0/net/protocol.rb:191:in `readuntil'",
"/var/lang/lib/ruby/2.7.0/net/protocol.rb:201:in `readline'",
"/var/lang/lib/ruby/2.7.0/net/http/response.rb:42:in `read_status_line'",
"/var/lang/lib/ruby/2.7.0/net/http/response.rb:31:in `read_new'",
"/var/lang/lib/ruby/2.7.0/net/http.rb:1528:in `block in transport_request'",
"/var/lang/lib/ruby/2.7.0/net/http.rb:1519:in `catch'",
"/var/lang/lib/ruby/2.7.0/net/http.rb:1519:in `transport_request'",
"/var/lang/lib/ruby/2.7.0/net/http.rb:1492:in `request'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/remote/http/default.rb:118:in `response_for'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/remote/http/default.rb:77:in `request'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/remote/http/common.rb:59:in `call'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/remote/bridge.rb:592:in `execute'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/remote/bridge.rb:52:in `create_session'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/common/driver.rb:314:in `block in create_bridge'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/common/driver.rb:312:in `tap'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/common/driver.rb:312:in `create_bridge'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/common/driver.rb:74:in `initialize'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/common/driver.rb:47:in `new'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver/common/driver.rb:47:in `for'",
"/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-4.3.0/lib/selenium/webdriver.rb:89:in `for'",
"/var/task/lambda_function.rb:19:in `setup_driver'",
"/var/task/lambda_function.rb:7:in `lambda_handler'"
]
}
I have already added memory and timeout seconds to the lambda function but it still fails. This is odd because it works locally but not on the actual AWS Lambda.
Related
I am getting this error when perform following for health check:
require 'grpc/health/v1/health_pb'
require 'grpc/health/checker'
class HealthCheckService < Grpc::Health::V1::Health::Service
def check(req, req_view)
checker = Grpc::Health::Checker.new
checker.check(req, req_view)
end
end
Error is:
GRPC::NotFound:5:unknown cause.
Anyone has faced this issue before. really would appreciate for help.
Have you installed grpc and gprc-tools?
gem install grpc
gem install grpc-tools
I'm entirely unfamiliar with Ruby but familiar with gRPC.
Your code (with a tweak) works for me:
require 'grpc/health/v1/health_pb'
require 'grpc/health/checker'
class HealthCheckService < Grpc::Health::V1::Health::Service
def check(req, req_view)
checker = Grpc::Health::Checker.new
checker.set_status_for_services(
Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING,
"foo",
"bar"
)
checker.check(req, req_view)
end
end
def main
s = GRPC::RpcServer.new
s.add_http2_port("0.0.0.0:50051",:this_port_is_insecure)
s.handle(HealthCheckService)
s.run_till_terminated_or_interrupted([1,"int","SIGQUIT"])
end
main
And then, downloading health.proto, I can:
for SERVICE in "foo" "bar" "baz"
do
grpcurl \
-plaintext \
--proto health.proto \
-d "{\"service\":\"${SERVICE}\"}" \
localhost:50051 \
grpc.health.v1.Health/Check
{
"status": "SERVING"
}
{
"status": "SERVING"
}
ERROR:
Code: NotFound
Message: unknown cause
I am following the very basic tutorial found here: http://guides.rubygems.org/make-your-own-gem/
hola_username.rb:
class Hola
def self.hi
puts "Hello world!"
end
end
hola_username.gemspec:
Gem::Specification.new do |s|
s.name = 'hola_username'
s.version = '0.0.0'
s.date = '2010-04-28'
s.summary = "Hola!"
s.description = "A simple hello world gem"
s.authors = ["Surname Lastname"]
s.email = 'me.me#gmail.com'
s.files = ["lib/hola_username.rb"]
s.homepage =
'http://rubygems.org/gems/hola_username'
s.license = 'MIT'
end
That really is all there is to the project.
I can build my gem with
gem build .\hola_username.gemspec
I have also tested it by importing and executing the hi function of the Hola class and it works:
PS E:\hola_username> gem install .\hola_username-0.0.0.gem
Successfully installed hola_username-0.0.0
Parsing documentation for hola_username-0.0.0
Done installing documentation for hola_username after 0 seconds
1 gem installed
&
irb(main):001:0> require 'hola_username'
=> true
irb(main):002:0> Hola.hi
Hello world!
=> nil
irb(main):003:0>
But when I try to
gem push .\hola_username-0.0.0.gem
I get:
ERROR: While executing gem ... (Psych::SyntaxError)
(): control characters are not allowed at line 1 column 1
Any ideas?
Edit: I am on a windows 10 machine using ruby 2.0.0p598
Edit v01: Anything I put after gem push will result in the above error, doesn't seem to be a problem with the sample rubygem.
Edit v02: My credentials file that was generated in the .gem folder however stars with hex characters: fffe2d002d00.. Which might be the ones causing trouble?
My credentials file in .gem folder was encoded with UCS2 - Little Endian and converting it to UTF without BOM did the trick.
Although I have absolutey no idea why..
I'm absolutely baffled.. (And quite frustrated too.. )
For some reason guard isn't detecting file updates on osx, but only for certain files. It's almost like the regexp defined in the watch function isn't working or something..
I have created a brand new rails app for fiddling around following Ryans guard railscast --
http://railscasts.com/episodes/264-guard
And have the default guardfile as generated by;
guard init spec
which looks like this;
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard 'rspec', :cli => "--color --format nested --fail-fast" do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
# Rails example
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}# {m[2]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/# {m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/# {m[1]}_spec.rb"] }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch('config/routes.rb') { "spec/routing" }
watch('app/controllers/application_controller.rb') { "spec/controllers" }
# Capybara request specs
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
# Turnip features and steps
watch(%r{^spec/acceptance/(.+)\.feature$})
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end
If I edit application_controller.rb or a spec file in the spec dir, guard will autorun just fine.
But if I edit and save any other controller, nothing happens.
I have run guard as both guard and bundle exec guard with no difference; It just runs the full suite once then sits there at a prompt.
macbook pro os v10.6.8.
RVM with Ruby-1.9.3-p286 and Rails 3.2.8
rb-fsevent 0.9.2
One of my coworkers is running the exact same thing directly pulled from git with the same system specs (company issued mbp's), and it works for him.
When he edits app/home_controller.rb and just gives it an extra line or something, hits save.. the tests fire.
When I edit the file and hit save, nothing happens but if I edit app/application_controller.rb it fires..
I'm confused.. I'm frustrated.. I need help as I'm at a loss..
Thoughts?
It looks like a problem with rb-fsevent an OS X 10.6. You can try if an older version of rb-fsevent will work by setting a fixed version in your Gemfile like
gem 'rb-fsevent', '0.9.0'
or you can work around the issue by switching to polling:
bundle exec guard --force-polling
I wrote a collectd plugin in ruby that is suppose to check passengers status and report back the various metrics. When I test my script on the all works well, but when I attempt to run my script through collectd it fails with the following message.
"ERROR: You are not authorized to query the status for this Phusion Passenger instance. Please try again with 'sudo'."
I then changed my ruby script to use the sudo command for passenger status which resulted in
"exec plugin: exec_read_one: error = sudo: sorry, you must have a tty to run sudo"
I then tried getting collectd to run the script as root but I got the following
"exec plugin: Cowardly refusing to exec program as root."
I am not sure what else I can try. the command that is failing when used by a user other that root is passenger-status
Here is the script
#!/usr/bin/env ruby
require 'getoptlong'
# The name of the collectd plugin, something like apache, memory, mysql, interface, ...
PLUGIN_NAME = 'passenger-status'
def usage
puts("#{$0} -h [-i ]")
exit
end
# Main
begin
# Sync stdout so that it will flush to collectd properly.
$stdout.sync = true
# Parse command line options
hostname = nil
sampling_interval = 20 # sec, Default value
opts = GetoptLong.new(
[ '--hostid', '-h', GetoptLong::REQUIRED_ARGUMENT ],
[ '--sampling-interval', '-i', GetoptLong::OPTIONAL_ARGUMENT ]
)
opts.each do |opt, arg|
case opt
when '--hostid'
hostname = arg
when '--sampling-interval'
sampling_interval = arg.to_i
end
end
usage if !hostname
# Collection loop
while true do
start_run = Time.now.to_i
next_run = start_run + sampling_interval
# collectd data and print the values
data = `passenger-status`
max = data.match(/max (.*)/).to_s.split.last
count = data.match(/count (.*)/).to_s.split.last
active = data.match(/active (.*)/).to_s.split.last
inactive = data.match(/inactive (.*)/).to_s.split.last
waiting = data.match(/Waiting on global queue: ([\d]+)/).to_s.split.last
puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-max_allowed_connections #{start_run}:#{max}")
puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-thread_count #{start_run}:#{count}")
puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-threads_active #{start_run}:#{active}")
puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-threads_inactive #{start_run}:#{inactive}")
puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-waiting_in_queue #{start_run}:#{waiting}")
# sleep to make the interval
while((time_left = (next_run - Time.now.to_i)) > 0) do
sleep(time_left)
end
end
end
Looking into the phusion_passenger/admin_tools/server_instance.rb file I was able to determine what file passenger was using to make the determination weather a user would be able to run the passenger-status command or not.
filename = "#{#generation_path}/passenger-status-password.txt"
password = File.open(filename, "rb") do |f|
f.read
end
rescue Errno::EACCES
raise RoleDeniedError
the file it was trying to read was passenger-status-password.txt this file is located in the /tmp/passenger.1.0.19198/generation-1/directory for Passenger version 3.0.9 on CentOS 5.7. I chmod'd the file to 644 and this fixed the issue. this solution also applies if someone wants to run the passenger-status command without sudo.
I'm trying to build a ruby gem around a C extension. The C extension compiles fine using the ruby extconf.rb; make; sudo make install routine, but when I try to build a gem using rake, the process terminates with the error at the bottom of this trace.
I'm using the post here, with the same directory structure, to create the gem.
What's wrong with my configuration? My gemspec and Rakefile are below the trace (the gem is called netconf).
// Trace
** Execute copy:netconf:i686-linux:1.9.2
install -c tmp/i686-linux/netconf/1.9.2/netconf.so lib/netconf/netconf.so
** Execute compile:netconf:i686-linux
** Execute compile:i686-linux
** Execute compile
** Invoke chmod (first_time)
** Execute chmod
** Execute build
rake aborted!
ERROR: While executing gem ... (Gem::InvalidSpecificationException)
["extconf.rb", "netconf.o", "netconf.so"] are not files
// netconf.gemspec
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "netconf/version"
Gem::Specification.new do |s|
s.name = "netconf"
s.version = Netconf::VERSION
s.authors = ["..."]
s.email = ["..."]
s.homepage = "..."
s.summary = %q{A tool to access and write Ubuntu network configuration}
s.description = %q{Uses ifconfig and other C system calls to access network configurations on a Ubuntu install.}
s.rubyforge_project = "netconf"
s.files = `git ls-files`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
s.extensions = ["ext/netconf/extconf.rb"]
end
// Rakefile
require 'rake'
require 'rake/extensiontask'
require 'bundler'
Rake::ExtensionTask.new("netconf") do |extension|
extension.lib_dir = "lib/netconf"
end
task :chmod do
File.chmod(0775, 'lib/netconf/netconf.so')
end
task :build => [:clean, :compile, :chmod]
Bundler::GemHelper.install_tasks
I got this error because I hadn't commited my updates with git yet.
s.files = `git ls-files`.split("\n")
That line is directly using git, and probably causing this error. Just do
git add .
git commit -a -m "init"
FWIW, I had a similar issue where
s.files = `git ls-files`.split("\n")
was
s.files = `git ls-files`.split('\n')
, where the single quotes were preventing the file list from splitting properly. Changing to double quotes fixed the issue for me.