github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/service/api_middleware_test.go (about)

     1  package service
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/evergreen-ci/evergreen"
    11  	"github.com/evergreen-ci/evergreen/db"
    12  	"github.com/evergreen-ci/evergreen/model/host"
    13  	"github.com/evergreen-ci/evergreen/model/task"
    14  	"github.com/evergreen-ci/evergreen/testutil"
    15  	"github.com/gorilla/context"
    16  	"github.com/gorilla/mux"
    17  	. "github.com/smartystreets/goconvey/convey"
    18  	"github.com/smartystreets/goconvey/convey/reporting"
    19  )
    20  
    21  func init() {
    22  	reporting.QuietMode()
    23  }
    24  
    25  func TestCheckHostWrapper(t *testing.T) {
    26  	h1 := host.Host{
    27  		Id:          "h1",
    28  		Secret:      "swordfish",
    29  		RunningTask: "t1",
    30  	}
    31  	t1 := task.Task{
    32  		Id:     "t1",
    33  		Secret: "password",
    34  		HostId: "h1",
    35  	}
    36  
    37  	Convey("With a simple checkTask and checkHost-wrapped route", t, func() {
    38  		if err := db.ClearCollections(host.Collection, task.Collection); err != nil {
    39  			t.Fatalf("clearing db: %v", err)
    40  		}
    41  		var ctx map[interface{}]interface{}
    42  		as, err := NewAPIServer(testutil.TestConfig(), nil)
    43  		if err != nil {
    44  			t.Fatalf("creating test API server: %v", err)
    45  		}
    46  		root := mux.NewRouter()
    47  		root.HandleFunc("/{taskId}/", as.checkTask(true, as.checkHost(
    48  			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    49  				ctx = context.GetAll(r)
    50  				as.WriteJSON(w, http.StatusOK, nil)
    51  			}),
    52  		)))
    53  
    54  		Convey("and documents representing a proper host-task relationship", func() {
    55  			So(t1.Insert(), ShouldBeNil)
    56  			So(h1.Insert(), ShouldBeNil)
    57  
    58  			w := httptest.NewRecorder()
    59  			r, err := http.NewRequest("GET", "/t1/", nil)
    60  			if err != nil {
    61  				t.Fatalf("building request: %v", err)
    62  			}
    63  
    64  			Convey("a request without proper task fields should fail", func() {
    65  				root.ServeHTTP(w, r)
    66  				So(w.Code, ShouldEqual, http.StatusConflict)
    67  
    68  				Convey("and attach nothing to the context", func() {
    69  					So(ctx[apiTaskKey], ShouldBeNil)
    70  					So(ctx[apiHostKey], ShouldBeNil)
    71  				})
    72  			})
    73  			Convey("a request with proper task fields but no host fields should not pass", func() {
    74  				r.Header.Add(evergreen.TaskSecretHeader, t1.Secret)
    75  				root.ServeHTTP(w, r)
    76  				So(w.Code, ShouldEqual, http.StatusBadRequest)
    77  
    78  				Convey("and attach nothing to the context", func() {
    79  					So(ctx[apiTaskKey], ShouldBeNil)
    80  					So(ctx[apiHostKey], ShouldBeNil)
    81  				})
    82  			})
    83  			Convey("a request with proper task fields and host fields should pass", func() {
    84  				r.Header.Add(evergreen.TaskSecretHeader, t1.Secret)
    85  				r.Header.Add(evergreen.HostHeader, h1.Id)
    86  				r.Header.Add(evergreen.HostSecretHeader, h1.Secret)
    87  				root.ServeHTTP(w, r)
    88  				So(w.Code, ShouldEqual, http.StatusOK)
    89  
    90  				Convey("and attach the and host to the context", func() {
    91  					So(ctx[apiTaskKey], ShouldNotBeNil)
    92  					So(ctx[apiHostKey], ShouldNotBeNil)
    93  					asHost, ok := ctx[apiHostKey].(*host.Host)
    94  					So(ok, ShouldBeTrue)
    95  					So(asHost.Id, ShouldEqual, h1.Id)
    96  					Convey("with an updated LastCommunicationTime", func() {
    97  						So(asHost.LastCommunicationTime, ShouldHappenWithin, time.Second, time.Now())
    98  					})
    99  				})
   100  			})
   101  			Convey("a request with the wrong host secret should fail", func() {
   102  				r.Header.Add(evergreen.TaskSecretHeader, t1.Secret)
   103  				r.Header.Add(evergreen.HostHeader, h1.Id)
   104  				r.Header.Add(evergreen.HostSecretHeader, "bad thing!!!")
   105  				root.ServeHTTP(w, r)
   106  				So(w.Code, ShouldEqual, http.StatusConflict)
   107  				msg, _ := ioutil.ReadAll(w.Body)
   108  				So(string(msg), ShouldContainSubstring, "secret")
   109  
   110  				Convey("and attach nothing to the context", func() {
   111  					So(ctx[apiTaskKey], ShouldBeNil)
   112  					So(ctx[apiHostKey], ShouldBeNil)
   113  				})
   114  			})
   115  		})
   116  		Convey("and documents representing a mismatched host-task relationship", func() {
   117  			h2 := host.Host{
   118  				Id:          "h2",
   119  				Secret:      "swordfish",
   120  				RunningTask: "t29",
   121  			}
   122  			t2 := task.Task{
   123  				Id:     "t2",
   124  				Secret: "password",
   125  				HostId: "h50",
   126  			}
   127  			So(t2.Insert(), ShouldBeNil)
   128  			So(h2.Insert(), ShouldBeNil)
   129  
   130  			w := httptest.NewRecorder()
   131  			r, err := http.NewRequest("GET", "/t2/", nil)
   132  			if err != nil {
   133  				t.Fatalf("building request: %v", err)
   134  			}
   135  
   136  			Convey("a request with proper task fields and host fields should fail", func() {
   137  				r.Header.Add(evergreen.TaskSecretHeader, t2.Secret)
   138  				r.Header.Add(evergreen.HostHeader, h2.Id)
   139  				r.Header.Add(evergreen.HostSecretHeader, h2.Secret)
   140  				root.ServeHTTP(w, r)
   141  				So(w.Code, ShouldEqual, http.StatusConflict)
   142  				msg, _ := ioutil.ReadAll(w.Body)
   143  				So(string(msg), ShouldContainSubstring, "should be running")
   144  
   145  				Convey("and attach the and host to the context", func() {
   146  					So(ctx[apiTaskKey], ShouldBeNil)
   147  					So(ctx[apiHostKey], ShouldBeNil)
   148  				})
   149  			})
   150  		})
   151  	})
   152  	Convey("With a checkTask and checkHost-wrapped route using URL params", t, func() {
   153  		if err := db.ClearCollections(host.Collection, task.Collection); err != nil {
   154  			t.Fatalf("clearing db: %v", err)
   155  		}
   156  		var ctx map[interface{}]interface{}
   157  		as, err := NewAPIServer(testutil.TestConfig(), nil)
   158  		if err != nil {
   159  			t.Fatalf("creating test API server: %v", err)
   160  		}
   161  		root := mux.NewRouter()
   162  		root.HandleFunc("/{taskId}/{hostId}", as.checkTask(true, as.checkHost(
   163  			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   164  				ctx = context.GetAll(r)
   165  				as.WriteJSON(w, http.StatusOK, nil)
   166  			}),
   167  		)))
   168  
   169  		Convey("and documents representing a proper host-task relationship", func() {
   170  
   171  			So(t1.Insert(), ShouldBeNil)
   172  			So(h1.Insert(), ShouldBeNil)
   173  
   174  			w := httptest.NewRecorder()
   175  			r, err := http.NewRequest("GET", "/t1/h1", nil)
   176  			if err != nil {
   177  				t.Fatalf("building request: %v", err)
   178  			}
   179  
   180  			Convey("a request with proper host params and fields should pass", func() {
   181  				r.Header.Add(evergreen.TaskSecretHeader, t1.Secret)
   182  				r.Header.Add(evergreen.HostSecretHeader, h1.Secret)
   183  				root.ServeHTTP(w, r)
   184  				So(w.Code, ShouldEqual, http.StatusOK)
   185  
   186  				Convey("and attach the and host to the context", func() {
   187  					So(ctx[apiTaskKey], ShouldNotBeNil)
   188  					So(ctx[apiHostKey], ShouldNotBeNil)
   189  					asHost, ok := ctx[apiHostKey].(*host.Host)
   190  					So(ok, ShouldBeTrue)
   191  					So(asHost.Id, ShouldEqual, h1.Id)
   192  					Convey("with an updated LastCommunicationTime", func() {
   193  						So(asHost.LastCommunicationTime, ShouldHappenWithin, time.Second, time.Now())
   194  					})
   195  				})
   196  			})
   197  			Convey("a request with the wrong host secret should fail", func() {
   198  				r.Header.Add(evergreen.TaskSecretHeader, t1.Secret)
   199  				r.Header.Add(evergreen.HostSecretHeader, "bad thing!!!")
   200  				root.ServeHTTP(w, r)
   201  				So(w.Code, ShouldEqual, http.StatusConflict)
   202  				msg, _ := ioutil.ReadAll(w.Body)
   203  				So(string(msg), ShouldContainSubstring, "secret")
   204  
   205  				Convey("and attach nothing to the context", func() {
   206  					So(ctx[apiTaskKey], ShouldBeNil)
   207  					So(ctx[apiHostKey], ShouldBeNil)
   208  				})
   209  			})
   210  		})
   211  	})
   212  }