anchor.diff:         end}}
        ]}.
   
  +basic_env_node_list_tests(#req_config{name = Name}=ReqConfig) ->
  +    Label = " (" ++ Name ++ ")",
  +    {foreach,
  +     fun() -> ok = db_tool:truncate_nodes_table() end,
  +     fun(_) -> cleanup end,
  +     [
  +      {"no such environment is a 404" ++ Label,
  +       fun() ->
  +               NoSuch = "/organizations/clownco/environments/no-such-env/nodes",
  +               {ok, Code, _H, Body} = chef_req:request(get, NoSuch, ReqConfig),
  +               ?assertEqual("404", Code),
  +               Msg = <<"{\"error\":[\"Cannot load environment no-such-env\"]}">>,
  +               ?assertEqual(Msg, Body)
  +       end},
  +
  +      {"environment list nodes, single node" ++ Label,
  +       fun() ->
  +               {AName, AUrl} = create_node("clownco", ReqConfig),
  +               Path = "/organizations/clownco/environments/_default/nodes",
  +               {ok, Code, _H, Body} = chef_req:request(get, Path, ReqConfig),
  +               ?assertEqual("200", Code),
  +               NodeList = ejson:decode(Body),
  +               ?assertEqual({[{AName, AUrl}]}, NodeList)
  +       end}
  +
  +      ,{timeout, 60, {"environment list more than one nodes" ++ Label,
  +       fun() ->
  +               NamePairs = [ create_node("clownco", ReqConfig) || _I <- lists:seq(1, 5) ],
  +               Path = "/organizations/clownco/nodes",
  +               {ok, Code, _H, Body} = chef_req:request(get, Path, ReqConfig),
  +               ?assertEqual("200", Code),
  +               {NodeList} = ejson:decode(Body),
  +               ?assertEqual(lists:sort(NamePairs), lists:sort(NodeList))
  +       end}}
  +      
  +     ]}.
  +               
   node_permissions_tests(_UserConfig, WeakClientConfig) ->
       Path = "/organizations/clownco/nodes",
       [
  
positive.code:      end}}}.
  
  named_node_permissions(UserConfig, ClientConfig, WeakClientConfig) ->
      {UserNode, _UserNodeUrl} = create_node("clownco", UserConfig),
      {ClientNode, _ClientNodeUrl} = create_node("clownco", ClientConfig),
      Path = "/organizations/clownco/nodes/",
      [{"admin user can read client created node",
        fun() ->
                NodePath = Path ++ ClientNode,
                ?assertEqual("200", code_for_request(get, NodePath, UserConfig))
        end},
  
       {"client can read user created node",
        fun() ->
                NodePath = Path ++ UserNode,
                ?assertEqual("200", code_for_request(get, NodePath, ClientConfig))
        end},
  
       {"weak client cannot read user created node",
        fun() ->
                NodePath = Path ++ UserNode,
                ?assertEqual("403", code_for_request(get, NodePath, WeakClientConfig))
        end},
  
       {"weak client cannot read client created node",
        fun() ->
                NodePath = Path ++ ClientNode,
                ?assertEqual("403", code_for_request(get, NodePath, WeakClientConfig))
        end},
  
       {"weak client cannot update client created node",
        fun() ->
                NodePath = Path ++ ClientNode,
                {_Name, SampleNode} = sample_node(ClientNode),
                ?assertEqual("403", code_for_request(put, NodePath, SampleNode, WeakClientConfig))
        end},
  
       {"weak client cannot delete client created node",
        fun() ->
                NodePath = Path ++ ClientNode,
                ?assertEqual("403", code_for_request(delete, NodePath, WeakClientConfig))
        end},
  
       %% FIXME: probably should put these in their own block with
       %% foreach or setup or something since we depend on creation and
       %% after the deletion nobody else can use it.
       {"admin user can update client created node",
        fun() ->
                NodePath = Path ++ ClientNode,
                {_Name, SampleNode} = sample_node(ClientNode),
                ?assertEqual("200", code_for_request(put, NodePath, SampleNode, UserConfig))
        end},
  
       {"admin user can delete client created node",
        fun() ->
                NodePath = Path ++ ClientNode,
                ?assertEqual("200", code_for_request(delete, NodePath, UserConfig))
        end}
       %% TODO:
       %% Moar testing
       %% verify admin user has all perms on a client created node
       %% clarify what perms a client should have on an admin created node and test them.
      ].
      
  basic_named_node_ops(#req_config{name = Name}=ReqConfig) ->
      Label = " (" ++ Name ++ ")",
      {AName, _AUrl} = create_node("clownco", ReqConfig),
      Path = "/organizations/clownco/nodes/",
      [
       {"GET a non-existing node" ++ Label,
        fun() ->
                NoName = "a-node-that-does-not-exist-xxx",
                NoNodePath = Path ++ NoName,
                {ok, Code, _H, Body} = chef_req:request(get, NoNodePath, ReqConfig),
                ?assertEqual("404", Code),
                Expect = iolist_to_binary(["{\"error\":[\"node '", NoName,
                                           "' not found\"]}"]),
                ?assertEqual(Expect, Body)
        end},
  
       {"Fetch, modify, verify, and delete a node" ++ Label,
        fun() ->
                %% GET the node
                NodePath = Path ++ AName,
                {ok, GetCode, _H1, Body1} = chef_req:request(get, NodePath, ReqConfig),
                ?assertEqual("200", GetCode),
                TheNode = ejson:decode(Body1),
                ?assertEqual(AName, ej:get({<<"name">>}, TheNode)),
  
                %% modify and PUT it back
                NewNode = ej:set({<<"normal">>}, TheNode, {[{<<"volume">>, 11}]}),
                NewNodeJson = ejson:encode(NewNode),
                {ok, PutCode, _H2, Body2} = chef_req:request(put, NodePath,
                                                             NewNodeJson, ReqConfig),
                ?assertEqual("200", PutCode),
                ?assertEqual(NewNodeJson, Body2),
  
                %% GET it and verify it has the new attribute
                {ok, GetCode2, _H3, Body3} = chef_req:request(get, NodePath, ReqConfig),
                ?assertEqual("200", GetCode2),
                GotNode = ejson:decode(Body3),
                ?assertEqual(11, ej:get({<<"normal">>, <<"volume">>}, GotNode)),
                
                %% DELETE it
                {ok, DelCode, _H4, Body4} = chef_req:request(delete, NodePath, ReqConfig),
                ?assertEqual("200", DelCode),
                ?assertEqual(NewNodeJson, Body4),
  
                %% verify we get a 404
                {ok, GetCode3, _H5, _Body5} = chef_req:request(get, NodePath, ReqConfig),
                ?assertEqual("404", GetCode3)
        end}
      ].
  
  basic_node_list_tests_for_config(#req_config{name = Name}=ReqConfig) ->
      Label = " (" ++ Name ++ ")",
  
negative.code:      end,
       fun({UserConfig, ClientConfig, WeakClientConfig}) ->
               [
                basic_env_node_list_tests(UserConfig),
                named_node_permissions(UserConfig, ClientConfig, WeakClientConfig),
                basic_named_node_ops(UserConfig),
                basic_named_node_ops(ClientConfig),
  