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

     1  package service
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"sort"
     9  
    10  	"github.com/evergreen-ci/evergreen/model/distro"
    11  	"github.com/evergreen-ci/evergreen/model/event"
    12  	"github.com/evergreen-ci/evergreen/model/host"
    13  	"github.com/evergreen-ci/evergreen/model/user"
    14  	"github.com/evergreen-ci/evergreen/util"
    15  	"github.com/evergreen-ci/evergreen/validator"
    16  	"github.com/gorilla/mux"
    17  )
    18  
    19  func (uis *UIServer) distrosPage(w http.ResponseWriter, r *http.Request) {
    20  	projCtx := MustHaveProjectContext(r)
    21  	distros, err := distro.Find(distro.All)
    22  
    23  	if err != nil {
    24  		message := fmt.Sprintf("error fetching distros: %v", err)
    25  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
    26  		http.Error(w, message, http.StatusInternalServerError)
    27  		return
    28  	}
    29  
    30  	sort.Sort(&sortableDistro{distros})
    31  
    32  	uis.WriteHTML(w, http.StatusOK, struct {
    33  		Distros     []distro.Distro
    34  		Keys        map[string]string
    35  		User        *user.DBUser
    36  		ProjectData projectContext
    37  		Flashes     []interface{}
    38  	}{distros, uis.Settings.Keys, GetUser(r), projCtx, PopFlashes(uis.CookieStore, r, w)},
    39  		"base", "distros.html", "base_angular.html", "menu.html")
    40  }
    41  
    42  func (uis *UIServer) modifyDistro(w http.ResponseWriter, r *http.Request) {
    43  	id := mux.Vars(r)["distro_id"]
    44  	shouldDeco := r.FormValue("deco") == "true"
    45  
    46  	u := MustHaveUser(r)
    47  
    48  	body := util.NewRequestReader(r)
    49  	defer body.Close()
    50  
    51  	b, err := ioutil.ReadAll(body)
    52  	if err != nil {
    53  		message := fmt.Sprintf("error reading request: %v", err)
    54  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
    55  		http.Error(w, message, http.StatusBadRequest)
    56  		return
    57  	}
    58  
    59  	oldDistro, err := distro.FindOne(distro.ById(id))
    60  	if err != nil {
    61  		message := fmt.Sprintf("error finding distro: %v", err)
    62  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
    63  		http.Error(w, message, http.StatusInternalServerError)
    64  		return
    65  	}
    66  
    67  	newDistro := *oldDistro
    68  
    69  	// attempt to unmarshal data into distros field for type validation
    70  	if err = json.Unmarshal(b, &newDistro); err != nil {
    71  		message := fmt.Sprintf("error unmarshaling request: %v", err)
    72  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
    73  		http.Error(w, message, http.StatusBadRequest)
    74  		return
    75  	}
    76  
    77  	// check that the resulting distro is valid
    78  	vErrs, err := validator.CheckDistro(&newDistro, &uis.Settings, false)
    79  	if err != nil {
    80  		message := fmt.Sprintf("error retrieving distroIds: %v", err)
    81  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
    82  		http.Error(w, message, http.StatusInternalServerError)
    83  		return
    84  	}
    85  
    86  	if len(vErrs) != 0 {
    87  		for _, e := range vErrs {
    88  			PushFlash(uis.CookieStore, r, w, NewErrorFlash(e.Error()))
    89  		}
    90  		uis.WriteJSON(w, http.StatusBadRequest, vErrs)
    91  		return
    92  	}
    93  
    94  	if err = newDistro.Update(); err != nil {
    95  		message := fmt.Sprintf("error updating distro: %v", err)
    96  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
    97  		http.Error(w, message, http.StatusBadRequest)
    98  		return
    99  	}
   100  
   101  	if shouldDeco {
   102  		err = host.DecommissionHostsWithDistroId(newDistro.Id)
   103  		if err != nil {
   104  			message := fmt.Sprintf("error decommissioning hosts: %v", err)
   105  			PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   106  			http.Error(w, message, http.StatusBadRequest)
   107  			return
   108  		}
   109  	}
   110  
   111  	event.LogDistroModified(id, u.Username(), newDistro)
   112  
   113  	message := fmt.Sprintf("Distro %v successfully updated.", id)
   114  	if shouldDeco {
   115  		message = fmt.Sprintf("Distro %v successfully updated and running hosts decommissioned", id)
   116  	}
   117  	PushFlash(uis.CookieStore, r, w, NewSuccessFlash(message))
   118  	uis.WriteJSON(w, http.StatusOK, "distro successfully updated")
   119  }
   120  
   121  func (uis *UIServer) removeDistro(w http.ResponseWriter, r *http.Request) {
   122  	id := mux.Vars(r)["distro_id"]
   123  
   124  	u := MustHaveUser(r)
   125  
   126  	d, err := distro.FindOne(distro.ById(id))
   127  	if err != nil {
   128  		message := fmt.Sprintf("error finding distro: %v", err)
   129  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   130  		http.Error(w, message, http.StatusInternalServerError)
   131  		return
   132  	}
   133  
   134  	if err = distro.Remove(id); err != nil {
   135  		message := fmt.Sprintf("error removing distro '%v': %v", id, err)
   136  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   137  		http.Error(w, message, http.StatusInternalServerError)
   138  		return
   139  	}
   140  
   141  	event.LogDistroRemoved(id, u.Username(), d)
   142  
   143  	PushFlash(uis.CookieStore, r, w, NewSuccessFlash(fmt.Sprintf("Distro %v successfully removed.", id)))
   144  	uis.WriteJSON(w, http.StatusOK, "distro successfully removed")
   145  }
   146  
   147  func (uis *UIServer) getDistro(w http.ResponseWriter, r *http.Request) {
   148  	id := mux.Vars(r)["distro_id"]
   149  
   150  	d, err := distro.FindOne(distro.ById(id))
   151  	if err != nil {
   152  		message := fmt.Sprintf("error fetching distro '%v': %v", id, err)
   153  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   154  		http.Error(w, message, http.StatusInternalServerError)
   155  		return
   156  	}
   157  
   158  	uis.WriteJSON(w, http.StatusOK, d)
   159  }
   160  
   161  func (uis *UIServer) addDistro(w http.ResponseWriter, r *http.Request) {
   162  	id, hasId := mux.Vars(r)["distro_id"]
   163  
   164  	u := MustHaveUser(r)
   165  
   166  	body := util.NewRequestReader(r)
   167  	defer body.Close()
   168  
   169  	b, err := ioutil.ReadAll(body)
   170  	if err != nil {
   171  		message := fmt.Sprintf("error adding distro: %v", err)
   172  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   173  		http.Error(w, err.Error(), http.StatusBadRequest)
   174  		return
   175  	}
   176  
   177  	var d distro.Distro
   178  
   179  	if err = json.Unmarshal(b, &d); err != nil {
   180  		message := fmt.Sprintf("error adding distro: %v", err)
   181  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   182  		http.Error(w, message, http.StatusBadRequest)
   183  		return
   184  	}
   185  
   186  	if hasId {
   187  		d.Id = id
   188  	}
   189  
   190  	vErrs, err := validator.CheckDistro(&d, &uis.Settings, true)
   191  	if err != nil {
   192  		message := fmt.Sprintf("error retrieving distroIds: %v", err)
   193  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   194  		http.Error(w, message, http.StatusInternalServerError)
   195  		return
   196  	}
   197  
   198  	if len(vErrs) != 0 {
   199  		for _, e := range vErrs {
   200  			PushFlash(uis.CookieStore, r, w, NewErrorFlash(e.Error()))
   201  		}
   202  		uis.WriteJSON(w, http.StatusBadRequest, vErrs)
   203  		return
   204  	}
   205  
   206  	if err = d.Insert(); err != nil {
   207  		message := fmt.Sprintf("error inserting distro '%v': %v", d.Id, err)
   208  		PushFlash(uis.CookieStore, r, w, NewErrorFlash(message))
   209  		uis.WriteJSON(w, http.StatusInternalServerError, err)
   210  		return
   211  	}
   212  
   213  	event.LogDistroAdded(d.Id, u.Username(), d)
   214  
   215  	PushFlash(uis.CookieStore, r, w, NewSuccessFlash(fmt.Sprintf("Distro %v successfully added.", d.Id)))
   216  	uis.WriteJSON(w, http.StatusOK, "distro successfully added")
   217  }
   218  
   219  type sortableDistro struct {
   220  	distros []distro.Distro
   221  }
   222  
   223  func (s *sortableDistro) Len() int {
   224  	return len(s.distros)
   225  }
   226  
   227  func (s *sortableDistro) Less(i, j int) bool {
   228  	return s.distros[i].Id < s.distros[j].Id
   229  }
   230  
   231  func (s *sortableDistro) Swap(i, j int) {
   232  	s.distros[i], s.distros[j] = s.distros[j], s.distros[i]
   233  }