lib/toxiproxy.rb in toxiproxy-0.0.2 vs lib/toxiproxy.rb in toxiproxy-0.1.0

- old
+ new

@@ -12,16 +12,17 @@ class NotFound < StandardError; end class ProxyExists < StandardError; end class InvalidToxic < StandardError; end - attr_reader :listen, :name + attr_reader :listen, :name, :enabled def initialize(options) @upstream = options[:upstream] @listen = options[:listen] || "localhost:0" @name = options[:name] + @enabled = options[:enabled] end # Forwardable doesn't support delegating class methods, so we resort to # `define_method` to delegate from Toxiproxy to #all, and from there to the # proxy collection. @@ -31,21 +32,30 @@ self.all.send(method, *args, &block) end end end + # Re-enables all proxies and disables all toxics. + def self.reset + request = Net::HTTP::Get.new("/reset") + response = http.request(request) + assert_response(response) + self + end + # Returns a collection of all currently active Toxiproxies. def self.all request = Net::HTTP::Get.new("/proxies") response = http.request(request) assert_response(response) proxies = JSON.parse(response.body).map { |name, attrs| self.new({ upstream: attrs["upstream"], listen: attrs["listen"], - name: attrs["name"] + name: attrs["name"], + enabled: attrs["enabled"] }) } Collection.new(proxies) end @@ -55,62 +65,96 @@ self.new(options).create end # Find a single proxy by name. def self.find_by_name(name = nil, &block) - proxy = self.all.find { |p| p.name == name.to_s } + self.all.find { |p| p.name == name.to_s } + end + + # Calls find_by_name and raises NotFound if not found + def self.find_by_name!(*args) + proxy = find_by_name(*args) raise NotFound, "#{name} not found in #{self.all.map(&:name).join(', ')}" unless proxy proxy end # If given a regex, it'll use `grep` to return a Toxiproxy::Collection. # Otherwise, it'll convert the passed object to a string and find the proxy by # name. def self.[](query) return grep(query) if query.is_a?(Regexp) - find_by_name(query) + find_by_name!(query) end + def self.populate(path) + proxies = JSON.parse(File.read(path), symbolize_names: true) + proxies = proxies.map { |proxy| self.new(proxy) } + + proxies.each do |proxy| + proxy.create unless find_by_name(proxy.name) + end + end + # Set an upstream toxic. def upstream(toxic = nil, attrs = {}) return @upstream unless toxic - collection = ToxicCollection.new(self) + collection = ToxicCollection.new([self]) collection.upstream(toxic, attrs) collection end # Set a downstream toxic. def downstream(toxic, attrs = {}) - collection = ToxicCollection.new(self) + collection = ToxicCollection.new([self]) collection.downstream(toxic, attrs) collection end # Simulates the endpoint is down, by closing the connection and no # longer accepting connections. This is useful to simulate critical system # failure, such as a data store becoming completely unavailable. def down(&block) - uptoxics = toxics(:upstream) - downtoxics = toxics(:downstream) - destroy + disable begin yield ensure - create - uptoxics.each(&:save) - downtoxics.each(&:save) + enable end end + # Disables a Toxiproxy. This will drop all active connections and stop the proxy from listening. + def disable + request = Net::HTTP::Post.new("/proxies/#{name}") + + hash = {enabled: false} + request.body = hash.to_json + + response = http.request(request) + assert_response(response) + self + end + + # Enables a Toxiproxy. This will cause the proxy to start listening again. + def enable + request = Net::HTTP::Post.new("/proxies/#{name}") + + hash = {enabled: true} + request.body = hash.to_json + + response = http.request(request) + assert_response(response) + self + end + # Create a Toxiproxy, proxying traffic from `@listen` (optional argument to # the constructor) to `@upstream`. `#down` `#upstream` or `#downstream` can at any time alter the health # of this connection. def create request = Net::HTTP::Post.new("/proxies") - hash = {upstream: upstream, name: name, listen: listen} + hash = {upstream: upstream, name: name, listen: listen, enabled: enabled} request.body = hash.to_json response = http.request(request) assert_response(response) @@ -126,12 +170,10 @@ response = http.request(request) assert_response(response) self end - private - # Returns a collection of the current toxics for a direction. def toxics(direction) unless VALID_DIRECTIONS.include?(direction.to_sym) raise InvalidToxic, "Toxic direction must be one of: [#{VALID_DIRECTIONS.join(', ')}], got: #{direction}" end @@ -149,9 +191,11 @@ }) } toxics end + + private def self.http @http ||= Net::HTTP.new(URI.host, URI.port) end