func serviceInstances(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "list-service-instances")
	services, _ := service.GetServicesByTeamKindAndNoRestriction("teams", u)
	sInstances, _ := service.GetServiceInstancesByServicesAndTeams(services, u)
	result := make([]service.ServiceModel, len(services))
	for i, s := range services {
		result[i].Service = s.Name
		for _, si := range sInstances {
			if si.ServiceName == s.Name {
				result[i].Instances = append(result[i].Instances, si.Name)
			}
		}
	}
	body, err := json.Marshal(result)
	if err != nil {
		return err
	}
	n, err := w.Write(body)
	if n != len(body) {
		return &errors.HTTP{Code: http.StatusInternalServerError, Message: "Failed to write the response body."}
	}
	return err
}
Beispiel #2
0
func removeUserFromTeam(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	email := r.URL.Query().Get(":user")
	teamName := r.URL.Query().Get(":team")
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "remove-user-from-team", "team="+teamName, "user="******"Team not found"}
	}
	if !team.ContainsUser(u) {
		msg := fmt.Sprintf("You are not authorized to remove a member from the team %s", team.Name)
		return &errors.HTTP{Code: http.StatusUnauthorized, Message: msg}
	}
	if len(team.Users) == 1 {
		msg := "You can not remove this user from this team, because it is the last user within the team, and a team can not be orphaned"
		return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
	}
	user, err := auth.GetUserByEmail(email)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	err = removeUserFromTeamInGandalf(user, team.Name)
	if err != nil {
		return nil
	}
	return removeUserFromTeamInDatabase(user, team)
}
Beispiel #3
0
func createTeam(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	var params map[string]string
	err := json.NewDecoder(r.Body).Decode(&params)
	if err != nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	name, ok := params["name"]
	if !ok {
		msg := "You must provide the team name"
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "create-team", name)
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	team := &auth.Team{Name: name, Users: []string{u.Email}}
	if err := conn.Teams().Insert(team); err != nil &&
		strings.Contains(err.Error(), "duplicate key error") {
		msg := "This team already exists"
		return &errors.HTTP{Code: http.StatusConflict, Message: msg}
	}
	return nil
}
Beispiel #4
0
Datei: app.go Projekt: nemx/tsuru
func unsetEnv(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	msg := "You must provide the list of environment variables, in JSON format"
	if r.Body == nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	var variables []string
	defer r.Body.Close()
	err := json.NewDecoder(r.Body).Decode(&variables)
	if err != nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	if len(variables) == 0 {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	appName := r.URL.Query().Get(":app")
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "unset-env", "app="+appName, fmt.Sprintf("envs=%s", variables))
	app, err := getApp(appName, u)
	if err != nil {
		return err
	}
	return app.UnsetEnvs(variables, true)
}
Beispiel #5
0
Datei: app.go Projekt: nemx/tsuru
func setEnv(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	msg := "You must provide the environment variables in a JSON object"
	if r.Body == nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	var variables map[string]string
	err := json.NewDecoder(r.Body).Decode(&variables)
	if err != nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	rec.Log(u.Email, "set-env", "app="+appName, variables)
	app, err := getApp(appName, u)
	if err != nil {
		return err
	}
	envs := make([]bind.EnvVar, 0, len(variables))
	for k, v := range variables {
		envs = append(envs, bind.EnvVar{Name: k, Value: v, Public: true})
	}
	return app.SetEnvs(envs, true)
}
Beispiel #6
0
Datei: app.go Projekt: nemx/tsuru
func setCName(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	msg := "You must provide the cname."
	if r.Body == nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	var v map[string]string
	err := json.NewDecoder(r.Body).Decode(&v)
	if err != nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: "Invalid JSON in request body."}
	}
	if _, ok := v["cname"]; !ok {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	rec.Log(u.Email, "set-cname", "app="+appName, "cname="+v["cname"])
	app, err := getApp(appName, u)
	if err != nil {
		return err
	}
	if err = app.SetCName(v["cname"]); err == nil {
		return nil
	}
	if err.Error() == "Invalid cname" {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	return err
}
func serviceInfo(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	serviceName := r.URL.Query().Get(":name")
	rec.Log(u.Email, "service-info", serviceName)
	_, err = getServiceOrError(serviceName, u)
	if err != nil {
		return err
	}
	instances := []service.ServiceInstance{}
	teams, err := u.Teams()
	if err != nil {
		return err
	}
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	teamsNames := auth.GetTeamsNames(teams)
	q := bson.M{"service_name": serviceName, "teams": bson.M{"$in": teamsNames}}
	err = conn.ServiceInstances().Find(q).All(&instances)
	if err != nil {
		return err
	}
	b, err := json.Marshal(instances)
	if err != nil {
		return nil
	}
	w.Write(b)
	return nil
}
func revokeServiceAccess(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	serviceName := r.URL.Query().Get(":service")
	teamName := r.URL.Query().Get(":team")
	rec.Log(u.Email, "revoke-service-access", "service="+serviceName, "team="+teamName)
	service, team, err := getServiceAndTeam(serviceName, teamName, u)
	if err != nil {
		return err
	}
	if len(service.Teams) < 2 {
		msg := "You can not revoke the access from this team, because it is the unique team with access to this service, and a service can not be orphaned"
		return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
	}
	err = service.RevokeAccess(team)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	return conn.Services().Update(bson.M{"_id": service.Name}, service)
}
Beispiel #9
0
// ChangePassword changes the password from the logged in user.
//
// It reads the request body in JSON format. The JSON in the request body
// should contain two attributes:
//
// - old: the old password
// - new: the new password
//
// This handler will return 403 if the password didn't match the user, or 412
// if the new password is invalid.
func ChangePassword(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	var body map[string]string
	err := json.NewDecoder(r.Body).Decode(&body)
	if err != nil {
		return &errors.Http{
			Code:    http.StatusBadRequest,
			Message: "Invalid JSON.",
		}
	}
	if body["old"] == "" || body["new"] == "" {
		return &errors.Http{
			Code:    http.StatusBadRequest,
			Message: "Both the old and the new passwords are required.",
		}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	if err := u.CheckPassword(body["old"]); err != nil {
		return &errors.Http{
			Code:    http.StatusForbidden,
			Message: "The given password didn't match the user's current password.",
		}
	}
	if !validation.ValidateLength(body["new"], passwordMinLen, passwordMaxLen) {
		return &errors.Http{
			Code:    http.StatusPreconditionFailed,
			Message: passwordError,
		}
	}
	u.Password = body["new"]
	u.HashPassword()
	return u.Update()
}
func serviceDelete(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "delete-service", r.URL.Query().Get(":name"))
	s, err := getServiceByOwner(r.URL.Query().Get(":name"), u)
	if err != nil {
		return err
	}
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	n, err := conn.ServiceInstances().Find(bson.M{"service_name": s.Name}).Count()
	if err != nil {
		return err
	}
	if n > 0 {
		msg := "This service cannot be removed because it has instances.\nPlease remove these instances before removing the service."
		return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
	}
	err = s.Delete()
	if err != nil {
		return err
	}
	w.WriteHeader(http.StatusNoContent)
	return nil
}
Beispiel #11
0
func teamList(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "list-teams")
	teams, err := u.Teams()
	if err != nil {
		return err
	}
	if len(teams) > 0 {
		var result []map[string]string
		for _, team := range teams {
			result = append(result, map[string]string{"name": team.Name})
		}
		b, err := json.Marshal(result)
		if err != nil {
			return err
		}
		n, err := w.Write(b)
		if err != nil {
			return err
		}
		if n != len(b) {
			return &errors.HTTP{Code: http.StatusInternalServerError, Message: "Failed to write response body."}
		}
	} else {
		w.WriteHeader(http.StatusNoContent)
	}
	return nil
}
Beispiel #12
0
func addUserToTeam(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	teamName := r.URL.Query().Get(":team")
	email := r.URL.Query().Get(":user")
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "add-user-to-team", "team="+teamName, "user="******"Team not found"}
	}
	if !team.ContainsUser(u) {
		msg := fmt.Sprintf("You are not authorized to add new users to the team %s", team.Name)
		return &errors.HTTP{Code: http.StatusUnauthorized, Message: msg}
	}
	user, err := auth.GetUserByEmail(email)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: "User not found"}
	}
	actions := []*action.Action{
		&addUserToTeamInGandalfAction,
		&addUserToTeamInDatabaseAction,
	}
	pipeline := action.NewPipeline(actions...)
	return pipeline.Execute(user.Email, u, team)
}
Beispiel #13
0
Datei: app.go Projekt: nemx/tsuru
func runCommand(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	w.Header().Set("Content-Type", "text")
	msg := "You must provide the command to run"
	if r.Body == nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	c, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	if len(c) < 1 {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	once := r.URL.Query().Get("once")
	rec.Log(u.Email, "run-command", "app="+appName, "command="+string(c))
	app, err := getApp(appName, u)
	if err != nil {
		return err
	}
	return app.Run(string(c), w, once == "true")
}
Beispiel #14
0
func RemoveUserFromTeam(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	email := r.URL.Query().Get(":user")
	team := r.URL.Query().Get(":team")
	u, err := t.User()
	if err != nil {
		return err
	}
	return removeUserFromTeam(email, team, u)
}
Beispiel #15
0
func AddUserToTeam(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	team := r.URL.Query().Get(":team")
	email := r.URL.Query().Get(":user")
	u, err := t.User()
	if err != nil {
		return err
	}
	return addUserToTeam(email, team, u)
}
Beispiel #16
0
Datei: app.go Projekt: nemx/tsuru
func appLog(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	var err error
	var lines int
	if l := r.URL.Query().Get("lines"); l != "" {
		lines, err = strconv.Atoi(l)
		if err != nil {
			msg := `Parameter "lines" must be an integer.`
			return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
		}
	} else {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: `Parameter "lines" is mandatory.`}
	}
	w.Header().Set("Content-Type", "application/json")
	source := r.URL.Query().Get("source")
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	extra := []interface{}{
		"app=" + appName,
		fmt.Sprintf("lines=%d", lines),
	}
	if source != "" {
		extra = append(extra, "source="+source)
	}
	if r.URL.Query().Get("follow") == "1" {
		extra = append(extra, "follow=1")
	}
	rec.Log(u.Email, "app-log", extra...)
	a, err := getApp(appName, u)
	if err != nil {
		return err
	}
	logs, err := a.LastLogs(lines, source)
	if err != nil {
		return err
	}
	encoder := json.NewEncoder(w)
	err = encoder.Encode(logs)
	if err != nil {
		return err
	}
	// TODO(fss): write an automated test for this code.
	if r.URL.Query().Get("follow") == "1" {
		l := app.NewLogListener(&a)
		defer l.Close()
		for log := range l.C {
			err := encoder.Encode([]app.Applog{log})
			if err != nil {
				break
			}
		}
	}
	return nil
}
Beispiel #17
0
// RemoveKeyFromUser removes a key from a user.
//
// This function is just an http wrapper around removeKeyFromUser. The latter function
// exists to be used in other places in the package without the http stuff (request and
// response).
func RemoveKeyFromUser(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	key, err := getKeyFromBody(r.Body)
	if err != nil {
		return err
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	return removeKeyFromUser(key, u)
}
func serviceInstance(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	instance, err := getServiceInstanceOrError(r.URL.Query().Get(":name"), u)
	if err != nil {
		return err
	}
	return json.NewEncoder(w).Encode(instance)
}
Beispiel #19
0
func appInfo(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	app, err := getApp(r.URL.Query().Get(":app"), u)
	if err != nil {
		return err
	}
	return json.NewEncoder(w).Encode(&app)
}
Beispiel #20
0
Datei: app.go Projekt: nemx/tsuru
func platformList(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "platform-list")
	platforms, err := app.Platforms()
	if err != nil {
		return err
	}
	return json.NewEncoder(w).Encode(platforms)
}
Beispiel #21
0
func restart(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	w.Header().Set("Content-Type", "text")
	u, err := t.User()
	if err != nil {
		return err
	}
	instance, err := getApp(r.URL.Query().Get(":app"), u)
	if err != nil {
		return err
	}
	return instance.Restart(w)
}
func serviceCreate(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	var sy serviceYaml
	err = goyaml.Unmarshal(body, &sy)
	if err != nil {
		return err
	}
	if _, ok := sy.Endpoint["production"]; !ok {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: "You must provide a production endpoint in the manifest file."}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "create-service", sy.Id, sy.Endpoint)
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	var teams []auth.Team
	err = conn.Teams().Find(bson.M{"users": u.Email}).All(&teams)
	if err != nil {
		return err
	}
	if len(teams) == 0 {
		msg := "In order to create a service, you should be member of at least one team"
		return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
	}
	n, err := conn.Services().Find(bson.M{"_id": sy.Id}).Count()
	if err != nil {
		return &errors.HTTP{Code: http.StatusInternalServerError, Message: err.Error()}
	}
	if n != 0 {
		msg := fmt.Sprintf("Service with name %s already exists.", sy.Id)
		return &errors.HTTP{Code: http.StatusInternalServerError, Message: msg}
	}
	s := service.Service{
		Name:       sy.Id,
		Endpoint:   sy.Endpoint,
		OwnerTeams: auth.GetTeamsNames(teams),
	}
	err = s.Create()
	if err != nil {
		return err
	}
	fmt.Fprint(w, "success")
	return nil
}
Beispiel #23
0
func unbindServiceInstance(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	instanceName, appName := r.URL.Query().Get(":instance"), r.URL.Query().Get(":app")
	u, err := t.User()
	if err != nil {
		return err
	}
	instance, a, err := getServiceInstace(instanceName, appName, u)
	if err != nil {
		return err
	}
	return instance.UnbindApp(&a)
}
Beispiel #24
0
func GetDocHandler(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	s, err := getServiceByOwner(r.URL.Query().Get(":name"), u)
	if err != nil {
		return err
	}
	w.Write([]byte(s.Doc))
	return nil
}
Beispiel #25
0
func createApp(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	var a app.App
	var japp jsonApp
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	if err = json.Unmarshal(body, &japp); err != nil {
		return err
	}
	a.Name = japp.Name
	a.Platform = japp.Platform
	if japp.Units == 0 {
		japp.Units = 1
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "create-app", "name="+japp.Name, "platform="+japp.Platform, fmt.Sprintf("units=%d", japp.Units))
	teams, err := u.Teams()
	if err != nil {
		return err
	}
	if len(teams) < 1 {
		msg := "In order to create an app, you should be member of at least one team"
		return &errors.Http{Code: http.StatusForbidden, Message: msg}
	}
	err = app.CreateApp(&a, japp.Units, teams)
	if err != nil {
		log.Printf("Got error while creating app: %s", err)
		if e, ok := err.(*errors.ValidationError); ok {
			return &errors.Http{Code: http.StatusBadRequest, Message: e.Message}
		}
		if strings.Contains(err.Error(), "key error") {
			msg := fmt.Sprintf(`There is already an app named "%s".`, a.Name)
			return &errors.Http{Code: http.StatusConflict, Message: msg}
		}
		return err
	}
	msg := map[string]string{
		"status":         "success",
		"repository_url": repository.GetUrl(a.Name),
	}
	jsonMsg, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	fmt.Fprintf(w, "%s", jsonMsg)
	return nil
}
Beispiel #26
0
func forceDeleteApp(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	a, err := getApp(r.URL.Query().Get(":app"), u)
	if err != nil {
		return err
	}
	app.ForceDestroy(&a)
	fmt.Fprint(w, "success")
	return nil
}
Beispiel #27
0
Datei: app.go Projekt: nemx/tsuru
func unbindServiceInstance(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	instanceName, appName := r.URL.Query().Get(":instance"), r.URL.Query().Get(":app")
	u, err := t.User()
	if err != nil {
		return err
	}
	instance, a, err := getServiceInstance(instanceName, appName, u)
	if err != nil {
		return err
	}
	rec.Log(u.Email, "unbind-app", "instance="+instanceName, "app="+appName)
	return instance.UnbindApp(a)
}
Beispiel #28
0
Datei: app.go Projekt: nemx/tsuru
func unsetCName(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	app, err := getApp(appName, u)
	if err != nil {
		return err
	}
	rec.Log(u.Email, "unset-cname", "app="+appName)
	return app.UnsetCName()
}
Beispiel #29
0
func Doc(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	sName := r.URL.Query().Get(":name")
	s, err := getServiceOrError(sName, u)
	if err != nil {
		return err
	}
	w.Write([]byte(s.Doc))
	return nil
}
Beispiel #30
0
Datei: app.go Projekt: nemx/tsuru
func createApp(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	var a app.App
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	if err = json.Unmarshal(body, &a); err != nil {
		return err
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "create-app", "name="+a.Name, "platform="+a.Platform)
	err = app.CreateApp(&a, u)
	if err != nil {
		log.Errorf("Got error while creating app: %s", err)
		if e, ok := err.(*errors.ValidationError); ok {
			return &errors.HTTP{Code: http.StatusBadRequest, Message: e.Message}
		}
		if _, ok := err.(app.NoTeamsError); ok {
			return &errors.HTTP{
				Code:    http.StatusBadRequest,
				Message: "In order to create an app, you should be member of at least one team",
			}
		}
		if e, ok := err.(*app.AppCreationError); ok {
			if e.Err == app.ErrAppAlreadyExists {
				return &errors.HTTP{Code: http.StatusConflict, Message: e.Error()}
			}
			if _, ok := e.Err.(*quota.QuotaExceededError); ok {
				return &errors.HTTP{
					Code:    http.StatusForbidden,
					Message: "Quota exceeded",
				}
			}
		}
		return err
	}
	msg := map[string]string{
		"status":         "success",
		"repository_url": repository.ReadWriteURL(a.Name),
	}
	jsonMsg, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	fmt.Fprintf(w, "%s", jsonMsg)
	return nil
}