| Index: third_party/grpc/src/ruby/bin/apis/pubsub_demo.rb
|
| diff --git a/third_party/grpc/src/ruby/bin/apis/pubsub_demo.rb b/third_party/grpc/src/ruby/bin/apis/pubsub_demo.rb
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..143ecc7a8fc1f064863c5134efb04e02c11e8d5e
|
| --- /dev/null
|
| +++ b/third_party/grpc/src/ruby/bin/apis/pubsub_demo.rb
|
| @@ -0,0 +1,256 @@
|
| +#!/usr/bin/env ruby
|
| +
|
| +# Copyright 2015, Google Inc.
|
| +# All rights reserved.
|
| +#
|
| +# Redistribution and use in source and binary forms, with or without
|
| +# modification, are permitted provided that the following conditions are
|
| +# met:
|
| +#
|
| +# * Redistributions of source code must retain the above copyright
|
| +# notice, this list of conditions and the following disclaimer.
|
| +# * Redistributions in binary form must reproduce the above
|
| +# copyright notice, this list of conditions and the following disclaimer
|
| +# in the documentation and/or other materials provided with the
|
| +# distribution.
|
| +# * Neither the name of Google Inc. nor the names of its
|
| +# contributors may be used to endorse or promote products derived from
|
| +# this software without specific prior written permission.
|
| +#
|
| +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +# pubsub_demo demos accesses the Google PubSub API via its gRPC interface
|
| +#
|
| +# $ GOOGLE_APPLICATION_CREDENTIALS=<path_to_service_account_key_file> \
|
| +# path/to/pubsub_demo.rb \
|
| +# [--action=<chosen_demo_action> ]
|
| +#
|
| +# There are options related to the chosen action, see #parse_args below.
|
| +# - the possible actions are given by the method names of NamedAction class
|
| +# - the default action is list_some_topics
|
| +
|
| +this_dir = File.expand_path(File.dirname(__FILE__))
|
| +lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
|
| +$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
| +$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
|
| +
|
| +require 'optparse'
|
| +
|
| +require 'grpc'
|
| +require 'googleauth'
|
| +require 'google/protobuf'
|
| +
|
| +require 'google/protobuf/empty'
|
| +require 'tech/pubsub/proto/pubsub'
|
| +require 'tech/pubsub/proto/pubsub_services'
|
| +
|
| +# creates a SSL Credentials from the production certificates.
|
| +def ssl_creds
|
| + GRPC::Core::ChannelCredentials.new()
|
| +end
|
| +
|
| +# Builds the metadata authentication update proc.
|
| +def auth_proc(opts)
|
| + auth_creds = Google::Auth.get_application_default
|
| + return auth_creds.updater_proc
|
| +end
|
| +
|
| +# Creates a stub for accessing the publisher service.
|
| +def publisher_stub(opts)
|
| + address = "#{opts.host}:#{opts.port}"
|
| + stub_clz = Tech::Pubsub::PublisherService::Stub # shorter
|
| + GRPC.logger.info("... access PublisherService at #{address}")
|
| + call_creds = GRPC::Core::CallCredentials.new(auth_proc(opts))
|
| + combined_creds = ssl_creds.compose(call_creds)
|
| + stub_clz.new(address, creds: combined_creds,
|
| + GRPC::Core::Channel::SSL_TARGET => opts.host)
|
| +end
|
| +
|
| +# Creates a stub for accessing the subscriber service.
|
| +def subscriber_stub(opts)
|
| + address = "#{opts.host}:#{opts.port}"
|
| + stub_clz = Tech::Pubsub::SubscriberService::Stub # shorter
|
| + GRPC.logger.info("... access SubscriberService at #{address}")
|
| + call_creds = GRPC::Core::CallCredentials.new(auth_proc(opts))
|
| + combined_creds = ssl_creds.compose(call_creds)
|
| + stub_clz.new(address, creds: combined_creds,
|
| + GRPC::Core::Channel::SSL_TARGET => opts.host)
|
| +end
|
| +
|
| +# defines methods corresponding to each interop test case.
|
| +class NamedActions
|
| + include Tech::Pubsub
|
| +
|
| + # Initializes NamedActions
|
| + #
|
| + # @param pub [Stub] a stub for accessing the publisher service
|
| + # @param sub [Stub] a stub for accessing the publisher service
|
| + # @param args [Args] provides access to the command line
|
| + def initialize(pub, sub, args)
|
| + @pub = pub
|
| + @sub = sub
|
| + @args = args
|
| + end
|
| +
|
| + # Removes the test topic if it exists
|
| + def remove_topic
|
| + name = test_topic_name
|
| + p "... removing Topic #{name}"
|
| + @pub.delete_topic(DeleteTopicRequest.new(topic: name))
|
| + p "removed Topic: #{name} OK"
|
| + rescue GRPC::BadStatus => e
|
| + p "Could not delete a topics: rpc failed with '#{e}'"
|
| + end
|
| +
|
| + # Creates a test topic
|
| + def create_topic
|
| + name = test_topic_name
|
| + p "... creating Topic #{name}"
|
| + resp = @pub.create_topic(Topic.new(name: name))
|
| + p "created Topic: #{resp.name} OK"
|
| + rescue GRPC::BadStatus => e
|
| + p "Could not create a topics: rpc failed with '#{e}'"
|
| + end
|
| +
|
| + # Lists topics in the project
|
| + def list_some_topics
|
| + p 'Listing topics'
|
| + p '-------------_'
|
| + list_project_topics.topic.each { |t| p t.name }
|
| + rescue GRPC::BadStatus => e
|
| + p "Could not list topics: rpc failed with '#{e}'"
|
| + end
|
| +
|
| + # Checks if a topics exists in a project
|
| + def check_exists
|
| + name = test_topic_name
|
| + p "... checking for topic #{name}"
|
| + exists = topic_exists?(name)
|
| + p "#{name} is a topic" if exists
|
| + p "#{name} is not a topic" unless exists
|
| + rescue GRPC::BadStatus => e
|
| + p "Could not check for a topics: rpc failed with '#{e}'"
|
| + end
|
| +
|
| + # Publishes some messages
|
| + def random_pub_sub
|
| + topic_name, sub_name = test_topic_name, test_sub_name
|
| + create_topic_if_needed(topic_name)
|
| + @sub.create_subscription(Subscription.new(name: sub_name,
|
| + topic: topic_name))
|
| + msg_count = rand(10..30)
|
| + msg_count.times do |x|
|
| + msg = PubsubMessage.new(data: "message #{x}")
|
| + @pub.publish(PublishRequest.new(topic: topic_name, message: msg))
|
| + end
|
| + p "Sent #{msg_count} messages to #{topic_name}, checking for them now."
|
| + batch = @sub.pull_batch(PullBatchRequest.new(subscription: sub_name,
|
| + max_events: msg_count))
|
| + ack_ids = batch.pull_responses.map { |x| x.ack_id }
|
| + p "Got #{ack_ids.size} messages; acknowledging them.."
|
| + @sub.acknowledge(AcknowledgeRequest.new(subscription: sub_name,
|
| + ack_id: ack_ids))
|
| + p "Test messages were acknowledged OK, deleting the subscription"
|
| + del_req = DeleteSubscriptionRequest.new(subscription: sub_name)
|
| + @sub.delete_subscription(del_req)
|
| + rescue GRPC::BadStatus => e
|
| + p "Could not do random pub sub: rpc failed with '#{e}'"
|
| + end
|
| +
|
| + private
|
| +
|
| + # test_topic_name is the topic name to use in this test.
|
| + def test_topic_name
|
| + unless @args.topic_name.nil?
|
| + return "/topics/#{@args.project_id}/#{@args.topic_name}"
|
| + end
|
| + now_text = Time.now.utc.strftime('%Y%m%d%H%M%S%L')
|
| + "/topics/#{@args.project_id}/#{ENV['USER']}-#{now_text}"
|
| + end
|
| +
|
| + # test_sub_name is the subscription name to use in this test.
|
| + def test_sub_name
|
| + unless @args.sub_name.nil?
|
| + return "/subscriptions/#{@args.project_id}/#{@args.sub_name}"
|
| + end
|
| + now_text = Time.now.utc.strftime('%Y%m%d%H%M%S%L')
|
| + "/subscriptions/#{@args.project_id}/#{ENV['USER']}-#{now_text}"
|
| + end
|
| +
|
| + # determines if the topic name exists
|
| + def topic_exists?(name)
|
| + topics = list_project_topics.topic.map { |t| t.name }
|
| + topics.include?(name)
|
| + end
|
| +
|
| + def create_topic_if_needed(name)
|
| + return if topic_exists?(name)
|
| + @pub.create_topic(Topic.new(name: name))
|
| + end
|
| +
|
| + def list_project_topics
|
| + q = "cloud.googleapis.com/project in (/projects/#{@args.project_id})"
|
| + @pub.list_topics(ListTopicsRequest.new(query: q))
|
| + end
|
| +end
|
| +
|
| +# Args is used to hold the command line info.
|
| +Args = Struct.new(:host, :port, :action, :project_id, :topic_name,
|
| + :sub_name)
|
| +
|
| +# validates the the command line options, returning them as an Arg.
|
| +def parse_args
|
| + args = Args.new('pubsub-staging.googleapis.com',
|
| + 443, 'list_some_topics', 'stoked-keyword-656')
|
| + OptionParser.new do |opts|
|
| + opts.on('--server_host SERVER_HOST', 'server hostname') do |v|
|
| + args.host = v
|
| + end
|
| + opts.on('--server_port SERVER_PORT', 'server port') do |v|
|
| + args.port = v
|
| + end
|
| +
|
| + # instance_methods(false) gives only the methods defined in that class.
|
| + scenes = NamedActions.instance_methods(false).map { |t| t.to_s }
|
| + scene_list = scenes.join(',')
|
| + opts.on("--action CODE", scenes, {}, 'pick a demo action',
|
| + " (#{scene_list})") do |v|
|
| + args.action = v
|
| + end
|
| +
|
| + # Set the remaining values.
|
| + %w(project_id topic_name sub_name).each do |o|
|
| + opts.on("--#{o} VALUE", "#{o}") do |v|
|
| + args[o] = v
|
| + end
|
| + end
|
| + end.parse!
|
| + _check_args(args)
|
| +end
|
| +
|
| +def _check_args(args)
|
| + %w(host port action).each do |a|
|
| + if args[a].nil?
|
| + raise OptionParser::MissingArgument.new("please specify --#{a}")
|
| + end
|
| + end
|
| + args
|
| +end
|
| +
|
| +def main
|
| + args = parse_args
|
| + pub, sub = publisher_stub(args), subscriber_stub(args)
|
| + NamedActions.new(pub, sub, args).method(args.action).call
|
| +end
|
| +
|
| +main
|
|
|