\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7<F<2PFAFZUP_xxnnx\F5\AF\B9\91\C8\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\DB\00CUZZxix‚\EB\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\C0\00\00b\00d\00\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00\001A!Q\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00!1AQ\FF\DA\00\00\00?\00\F6\00\00\00\00\00\00\00\00\00\00\A0\00\00\C5\CF\F8\E7Ó\FCjD~\B9^\AD\%\B3]\D8cs-\BBs,-\A0\00"\80\00%\B83rÏ^K~F\A4ea\00E\00\C6\EE=u\B1\9B\D1\00@\00r\BE8\F9:\FE5#.M\00\E7\CB\C9q\CBq\D6\F2\BE\B7\C7>\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7	\8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh
\00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€
\00$\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95
59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>C///</title>
</head>
require "tempfile"
require_relative "server"
require_relative "rest_request"

module ChefZero
  module RSpec
    module RSpecClassMethods
      attr_accessor :server
      attr_accessor :client_key
      attr_reader :request_log

      def clear_request_log
        @request_log = []
      end

      def set_server_options(chef_server_options)
        if server && chef_server_options != server.options
          server.stop
          self.server = nil
        end

        unless server
          # TODO: can this be logged easily?
          # pp :zero_opts => chef_server_options

          # Set up configuration so that clients will point to the server
          self.server = ChefZero::Server.new(chef_server_options)
          self.client_key = Tempfile.new(["chef_zero_client_key", ".pem"])
          client_key.write(ChefZero::PRIVATE_KEY)
          client_key.close
          # Start the server
          server.start_background
          server.on_response do |request, response|
            request_log << [ request, response ]
          end
        else
          server.clear_data
        end
        clear_request_log
      end
    end
    extend RSpecClassMethods

    def when_the_chef_server(description, *tags, &block)
      context "When the #{ChefZero::Dist::PRODUCT} server #{description}", *tags do
        extend WhenTheChefServerClassMethods
        include WhenTheChefServerInstanceMethods

        # Take the passed-in options

        # rubocop:disable Lint/UnderscorePrefixedVariableName
        define_singleton_method(:chef_server_options) do
          @chef_server_options ||= begin
            _chef_server_options = { port: 8900, signals: false, log_requests: true }
            _chef_server_options = _chef_server_options.merge(tags.last) if tags.last.is_a?(Hash)
            _chef_server_options = _chef_server_options.freeze
          end
        end
        # rubocop:enable Lint/UnderscorePrefixedVariableName

        # Merge in chef_server_options from let(:chef_server_options)
        def chef_server_options # rubocop:disable Lint/NestedMethodDefinition
          chef_server_options = self.class.chef_server_options.dup
          chef_server_options = chef_server_options.merge(chef_zero_opts) if respond_to?(:chef_zero_opts)
          chef_server_options
        end

        before chef_server_options[:server_scope] do
          if chef_server_options[:server_scope] != self.class.chef_server_options[:server_scope]
            raise "server_scope: #{chef_server_options[:server_scope]} will not be honored: it can only be set on when_the_chef_server!"
          end

          Log.info("Starting #{ChefZero::Dist::PRODUCT} server with options #{chef_server_options}")

          ChefZero::RSpec.set_server_options(chef_server_options)

          if chef_server_options[:organization]
            organization chef_server_options[:organization]
          end

          if defined?(Chef::Config)
            @old_chef_server_url = Chef::Config.chef_server_url
            @old_node_name = Chef::Config.node_name
            @old_client_key = Chef::Config.client_key
            if chef_server_options[:organization]
              Chef::Config.chef_server_url = "#{ChefZero::RSpec.server.url}/organizations/#{chef_server_options[:organization]}"
            else
              Chef::Config.chef_server_url = ChefZero::RSpec.server.url
            end
            Chef::Config.node_name = "admin"
            Chef::Config.client_key = ChefZero::RSpec.client_key.path
            Chef::Config.http_retry_count = 0
          end
        end

        if defined?(Chef::Config)
          after chef_server_options[:server_scope] do
            Chef::Config.chef_server_url = @old_chef_server_url
            Chef::Config.node_name = @old_node_name
            Chef::Config.client_key = @old_client_key
          end
        end

        instance_eval(&block)
      end
    end

    module WhenTheChefServerClassMethods
      def organization(name, org = "{}", &block)
        before(chef_server_options[:server_scope]) { organization(name, org, &block) }
      end

      def acl_for(path, data)
        before(chef_server_options[:server_scope]) { acl_for(path, data) }
      end

      def client(name, data, &block)
        before(chef_server_options[:server_scope]) { client(name, data, &block) }
      end

      def container(name, data, &block)
        before(chef_server_options[:server_scope]) { container(name, data, &block) }
      end

      def cookbook(name, version, data = {}, options = {}, &block)
        before(chef_server_options[:server_scope]) do
          cookbook(name, version, data, &block)
        end
      end

      def cookbook_artifact(name, identifier, data = {}, &block)
        before(chef_server_options[:server_scope]) { cookbook_artifact(name, identifier, data, &block) }
      end

      def data_bag(name, data, &block)
        before(chef_server_options[:server_scope]) { data_bag(name, data, &block) }
      end

      def environment(name, data, &block)
        before(chef_server_options[:server_scope]) { environment(name, data, &block) }
      end

      def group(name, data, &block)
        before(chef_server_options[:server_scope]) { group(name, data, &block) }
      end

      def node(name, data, &block)
        before(chef_server_options[:server_scope]) { node(name, data, &block) }
      end

      def org_invite(*usernames)
        before(chef_server_options[:server_scope]) { org_invite(*usernames) }
      end

      def org_member(*usernames)
        before(chef_server_options[:server_scope]) { org_member(*usernames) }
      end

      def policy(name, data, &block)
        before(chef_server_options[:server_scope]) { policy(name, data, &block) }
      end

      def policy_group(name, data, &block)
        before(chef_server_options[:server_scope]) { policy_group(name, data, &block) }
      end

      def role(name, data, &block)
        before(chef_server_options[:server_scope]) { role(name, data, &block) }
      end

      def sandbox(name, data, &block)
        before(chef_server_options[:server_scope]) { sandbox(name, data, &block) }
      end

      def user(name, data, &block)
        before(chef_server_options[:server_scope]) { user(name, data, &block) }
      end
    end

    module WhenTheChefServerInstanceMethods
      def organization(name, org = "{}", &block)
        ChefZero::RSpec.server.data_store.set([ "organizations", name, "org" ], dejsonize(org), :create_dir, :create)
        prev_org_name = @current_org
        @current_org = name
        prev_object_path = @current_object_path
        @current_object_path = "organizations/#{name}"
        if block_given?
          begin
            instance_eval(&block)
          ensure
            @current_org = prev_org_name
            @current_object_path = prev_object_path
          end
        end
      end

      def acl_for(path, data)
        ChefZero::RSpec.server.load_data({ "acls" => { path => data } }, current_org)
      end

      def acl(data)
        acl_for(@current_object_path, data)
      end

      def client(name, data, &block)
        with_object_path("clients/#{name}") do
          ChefZero::RSpec.server.load_data({ "clients" => { name => data } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def container(name, data, &block)
        with_object_path("containers/#{name}") do
          ChefZero::RSpec.server.load_data({ "containers" => { name => data } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def cookbook(name, version, data = {}, options = {}, &block)
        with_object_path("cookbooks/#{name}") do
          # If you didn't specify metadata.rb, we generate it for you. If you
          # explicitly set it to nil, that means you don't want it at all.
          if data.key?("metadata.rb")
            if data["metadata.rb"].nil?
              data.delete("metadata.rb")
            end
          else
            data["metadata.rb"] = "name #{name.inspect}; version #{version.inspect}"
          end
          ChefZero::RSpec.server.load_data({ "cookbooks" => { "#{name}-#{version}" => data.merge(options) } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def cookbook_artifact(name, identifier, data = {}, &block)
        with_object_path("cookbook_artifacts/#{name}") do
          # If you didn't specify metadata.rb, we generate it for you. If you
          # explicitly set it to nil, that means you don't want it at all.
          if data.key?("metadata.rb")
            if data["metadata.rb"].nil?
              data.delete("metadata.rb")
            end
          else
            data["metadata.rb"] = "name #{name.inspect}"
          end
          ChefZero::RSpec.server.load_data({ "cookbook_artifacts" => { "#{name}-#{identifier}" => data } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def data_bag(name, data, &block)
        with_object_path("data/#{name}") do
          ChefZero::RSpec.server.load_data({ "data" => { name => data } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def environment(name, data, &block)
        with_object_path("environments/#{name}") do
          ChefZero::RSpec.server.load_data({ "environments" => { name => data } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def group(name, data, &block)
        with_object_path("groups/#{name}") do
          ChefZero::RSpec.server.load_data({ "groups" => { name => data } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def node(name, data, &block)
        with_object_path("nodes/#{name}") do
          ChefZero::RSpec.server.load_data({ "nodes" => { name => data } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def org_invite(*usernames)
        ChefZero::RSpec.server.load_data({ "invites" => usernames }, current_org)
      end

      def org_member(*usernames)
        ChefZero::RSpec.server.load_data({ "members" => usernames }, current_org)
      end

      def policy(name, version, data, &block)
        with_object_path("policies/#{name}") do
          ChefZero::RSpec.server.load_data({ "policies" => { name => { version => data } } }, current_org)
          instance_eval(&block) if block_given?
        end
      end

      def policy_group(name, data, &block)
        with_object_path("policy_groups/#{name}") do
          ChefZero::RSpec.server.load_data({ "policy_groups" => { name => data } }, current_org)
 