github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/service/host.go (about)

     1  package service
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/evergreen-ci/evergreen"
    10  	"github.com/evergreen-ci/evergreen/model/event"
    11  	"github.com/evergreen-ci/evergreen/model/host"
    12  	"github.com/evergreen-ci/evergreen/model/task"
    13  	"github.com/evergreen-ci/evergreen/model/user"
    14  	"github.com/evergreen-ci/evergreen/util"
    15  	"github.com/gorilla/mux"
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  var (
    20  	validUpdateToStatuses = []string{
    21  		evergreen.HostRunning,
    22  		evergreen.HostQuarantined,
    23  		evergreen.HostDecommissioned,
    24  	}
    25  )
    26  
    27  const (
    28  	IncludeSpawnedHosts = "includeSpawnedHosts"
    29  )
    30  
    31  type uiParams struct {
    32  	Action string `json:"action"`
    33  
    34  	// the host ids for which an action applies
    35  	HostIds []string `json:"host_ids"`
    36  
    37  	// for the update status option
    38  	Status string `json:"status"`
    39  }
    40  
    41  func (uis *UIServer) hostPage(w http.ResponseWriter, r *http.Request) {
    42  	projCtx := MustHaveProjectContext(r)
    43  
    44  	vars := mux.Vars(r)
    45  	id := vars["host_id"]
    46  
    47  	h, err := host.FindOne(host.ById(id))
    48  	if err != nil {
    49  		uis.LoggedError(w, r, http.StatusInternalServerError, err)
    50  		return
    51  	}
    52  
    53  	if h == nil {
    54  		http.Error(w, "Host not found", http.StatusNotFound)
    55  		return
    56  	}
    57  
    58  	events, err := event.Find(event.AllLogCollection, event.MostRecentHostEvents(id, 50))
    59  	if err != nil {
    60  		uis.LoggedError(w, r, http.StatusInternalServerError, err)
    61  		return
    62  	}
    63  	runningTask := &task.Task{}
    64  	if h.RunningTask != "" {
    65  		runningTask, err = task.FindOne(task.ById(h.RunningTask))
    66  		if err != nil {
    67  			uis.LoggedError(w, r, http.StatusInternalServerError, err)
    68  			return
    69  		}
    70  	}
    71  
    72  	flashes := PopFlashes(uis.CookieStore, r, w)
    73  	uis.WriteHTML(w, http.StatusOK, struct {
    74  		Flashes     []interface{}
    75  		Events      []event.Event
    76  		Host        *host.Host
    77  		RunningTask *task.Task
    78  		User        *user.DBUser
    79  		ProjectData projectContext
    80  	}{flashes, events, h, runningTask, GetUser(r), projCtx},
    81  		"base", "host.html", "base_angular.html", "menu.html")
    82  }
    83  
    84  func (uis *UIServer) hostsPage(w http.ResponseWriter, r *http.Request) {
    85  	projCtx := MustHaveProjectContext(r)
    86  
    87  	includeSpawnedHosts, _ := strconv.ParseBool(r.FormValue(IncludeSpawnedHosts))
    88  	hosts, err := getHostsData(includeSpawnedHosts)
    89  	if err != nil {
    90  		uis.LoggedError(w, r, http.StatusInternalServerError, err)
    91  		return
    92  	}
    93  
    94  	flashes := PopFlashes(uis.CookieStore, r, w)
    95  	uis.WriteHTML(w, http.StatusOK, struct {
    96  		Flashes             []interface{}
    97  		Hosts               *hostsData
    98  		IncludeSpawnedHosts bool
    99  		User                *user.DBUser
   100  		ProjectData         projectContext
   101  	}{flashes, hosts, includeSpawnedHosts, GetUser(r), projCtx},
   102  		"base", "hosts.html", "base_angular.html", "menu.html")
   103  }
   104  
   105  func (uis *UIServer) modifyHost(w http.ResponseWriter, r *http.Request) {
   106  	_ = MustHaveUser(r)
   107  
   108  	vars := mux.Vars(r)
   109  	id := vars["host_id"]
   110  
   111  	host, err := host.FindOne(host.ById(id))
   112  	if err != nil {
   113  		uis.LoggedError(w, r, http.StatusInternalServerError, err)
   114  		return
   115  	}
   116  
   117  	if host == nil {
   118  		http.Error(w, "Host not found", http.StatusNotFound)
   119  		return
   120  	}
   121  
   122  	opts := &uiParams{}
   123  
   124  	if err = util.ReadJSONInto(util.NewRequestReader(r), opts); err != nil {
   125  		uis.LoggedError(w, r, http.StatusBadRequest, err)
   126  		return
   127  	}
   128  
   129  	// determine what action needs to be taken
   130  	switch opts.Action {
   131  	case "updateStatus":
   132  		currentStatus := host.Status
   133  		newStatus := opts.Status
   134  		if !util.SliceContains(validUpdateToStatuses, newStatus) {
   135  			http.Error(w, fmt.Sprintf("'%v' is not a valid status", newStatus), http.StatusBadRequest)
   136  			return
   137  		}
   138  		err := host.SetStatus(newStatus)
   139  		if err != nil {
   140  			uis.LoggedError(w, r, http.StatusInternalServerError, errors.Wrap(err, "Error updating host"))
   141  			return
   142  		}
   143  		msg := NewSuccessFlash(fmt.Sprintf("Host status successfully updated from '%v' to '%v'", currentStatus, host.Status))
   144  		PushFlash(uis.CookieStore, r, w, msg)
   145  		uis.WriteJSON(w, http.StatusOK, "Successfully updated host status")
   146  	default:
   147  		uis.WriteJSON(w, http.StatusBadRequest, fmt.Sprintf("Unrecognized action: %v", opts.Action))
   148  	}
   149  }
   150  
   151  func (uis *UIServer) modifyHosts(w http.ResponseWriter, r *http.Request) {
   152  	_ = MustHaveUser(r)
   153  
   154  	opts := &uiParams{}
   155  
   156  	if err := util.ReadJSONInto(util.NewRequestReader(r), opts); err != nil {
   157  		http.Error(w, err.Error(), http.StatusBadRequest)
   158  		return
   159  	}
   160  
   161  	hostIds := opts.HostIds
   162  	if len(hostIds) == 1 && strings.TrimSpace(hostIds[0]) == "" {
   163  		http.Error(w, "No host ID's found in request", http.StatusBadRequest)
   164  		return
   165  	}
   166  
   167  	// fetch all relevant hosts
   168  	hosts, err := host.Find(host.ByIds(hostIds))
   169  
   170  	if err != nil {
   171  		uis.LoggedError(w, r, http.StatusInternalServerError, errors.Wrap(err, "Error finding hosts"))
   172  		return
   173  	}
   174  	if len(hosts) == 0 {
   175  		http.Error(w, "No matching hosts found.", http.StatusBadRequest)
   176  		return
   177  	}
   178  
   179  	// determine what action needs to be taken
   180  	switch opts.Action {
   181  	case "updateStatus":
   182  		newStatus := opts.Status
   183  		if !util.SliceContains(validUpdateToStatuses, newStatus) {
   184  			http.Error(w, fmt.Sprintf("Invalid status: %v", opts.Status), http.StatusBadRequest)
   185  			return
   186  		}
   187  		numHostsUpdated := 0
   188  
   189  		for _, host := range hosts {
   190  			err := host.SetStatus(newStatus)
   191  			if err != nil {
   192  				uis.LoggedError(w, r, http.StatusInternalServerError, errors.Wrap(err, "Error updating host"))
   193  				return
   194  			}
   195  			numHostsUpdated += 1
   196  		}
   197  		msg := NewSuccessFlash(fmt.Sprintf("%v host(s) status successfully updated to '%v'",
   198  			numHostsUpdated, newStatus))
   199  		PushFlash(uis.CookieStore, r, w, msg)
   200  		return
   201  	default:
   202  		http.Error(w, fmt.Sprintf("Unrecognized action: %v", opts.Action), http.StatusBadRequest)
   203  		return
   204  	}
   205  }