Exemple #1
0
func appList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	extra := make([]interface{}, 0, 1)
	filter := &app.Filter{}
	if name := r.URL.Query().Get("name"); name != "" {
		extra = append(extra, fmt.Sprintf("name=%s", name))
		filter.NameMatches = name
	}
	if platform := r.URL.Query().Get("platform"); platform != "" {
		extra = append(extra, fmt.Sprintf("platform=%s", platform))
		filter.Platform = platform
	}
	if teamOwner := r.URL.Query().Get("teamOwner"); teamOwner != "" {
		extra = append(extra, fmt.Sprintf("teamowner=%s", teamOwner))
		filter.TeamOwner = teamOwner
	}
	if owner := r.URL.Query().Get("owner"); owner != "" {
		extra = append(extra, fmt.Sprintf("owner=%s", owner))
		filter.UserOwner = owner
	}
	if pool := r.URL.Query().Get("pool"); pool != "" {
		extra = append(extra, fmt.Sprintf("pool=%s", pool))
		filter.Pool = pool
	}
	locked, _ := strconv.ParseBool(r.URL.Query().Get("locked"))
	if locked {
		extra = append(extra, fmt.Sprintf("locked=%v", locked))
		filter.Locked = true
	}
	if status, ok := r.URL.Query()["status"]; ok {
		extra = append(extra, fmt.Sprintf("status=%s", strings.Join(status, ",")))
		filter.Statuses = status
	}
	rec.Log(u.Email, "app-list", extra...)
	contexts := permission.ContextsForPermission(t, permission.PermAppRead)
	if len(contexts) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	apps, err := app.List(appFilterByContext(contexts, filter))
	if err != nil {
		return err
	}
	if len(apps) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Set("Content-Type", "application/json")
	miniApps := make([]miniApp, len(apps))
	for i, app := range apps {
		miniApps[i], err = minifyApp(app)
		if err != nil {
			return err
		}
	}
	return json.NewEncoder(w).Encode(miniApps)
}
Exemple #2
0
// title: machine template list
// path: /iaas/templates
// method: GET
// produce: application/json
// responses:
//   200: OK
//   401: Unauthorized
func templatesList(w http.ResponseWriter, r *http.Request, token auth.Token) error {
	templates, err := iaas.ListTemplates()
	if err != nil {
		return err
	}
	contexts := permission.ContextsForPermission(token, permission.PermMachineTemplateRead)
	allowedIaaS := map[string]struct{}{}
	for _, c := range contexts {
		if c.CtxType == permission.CtxGlobal {
			allowedIaaS = nil
			break
		}
		if c.CtxType == permission.CtxIaaS {
			allowedIaaS[c.Value] = struct{}{}
		}
	}
	for i := 0; allowedIaaS != nil && i < len(templates); i++ {
		if _, ok := allowedIaaS[templates[i].IaaSName]; !ok {
			templates = append(templates[:i], templates[i+1:]...)
			i--
		}
	}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(templates)
}
Exemple #3
0
// title: service list
// path: /services
// method: GET
// produce: application/json
// responses:
//   200: List services
//   204: No content
//   401: Unauthorized
func serviceList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	contexts := permission.ContextsForPermission(t, permission.PermServiceRead)
	services, err := provisionReadableServices(t, contexts)
	if err != nil {
		return err
	}
	sInstances, err := service.GetServiceInstancesByServices(services)
	if err != nil {
		return err
	}
	results := make([]service.ServiceModel, len(services))
	for i, s := range services {
		results[i].Service = s.Name
		for _, si := range sInstances {
			if si.ServiceName == s.Name {
				results[i].Instances = append(results[i].Instances, si.Name)
			}
		}
	}
	if len(results) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(results)
}
Exemple #4
0
func machinesList(w http.ResponseWriter, r *http.Request, token auth.Token) error {
	machines, err := iaas.ListMachines()
	if err != nil {
		return err
	}
	contexts := permission.ContextsForPermission(token, permission.PermMachineRead)
	allowedIaaS := map[string]struct{}{}
	for _, c := range contexts {
		if c.CtxType == permission.CtxGlobal {
			allowedIaaS = nil
			break
		}
		if c.CtxType == permission.CtxIaaS {
			allowedIaaS[c.Value] = struct{}{}
		}
	}
	for i := 0; allowedIaaS != nil && i < len(machines); i++ {
		if _, ok := allowedIaaS[machines[i].Iaas]; !ok {
			machines = append(machines[:i], machines[i+1:]...)
			i--
		}
	}
	err = json.NewEncoder(w).Encode(machines)
	if err != nil {
		return err
	}
	return nil
}
Exemple #5
0
func listPoolsToUser(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "pool-list")
	teams := []string{}
	contexts := permission.ContextsForPermission(t, permission.PermAppCreate)
	for _, c := range contexts {
		if c.CtxType == permission.CtxGlobal {
			teams = nil
			break
		}
		if c.CtxType != permission.CtxTeam {
			continue
		}
		teams = append(teams, c.Value)
	}
	var filter bson.M
	if teams != nil {
		filter = bson.M{"teams": bson.M{"$in": teams}}
	}
	pools, err := provision.ListPools(filter)
	if err != nil {
		return err
	}
	poolsByTeam := []PoolsByTeam{}
	poolsByTeamMap := map[string]*PoolsByTeam{}
	for _, p := range pools {
		for _, t := range p.Teams {
			if poolsByTeamMap[t] == nil {
				poolsByTeam = append(poolsByTeam, PoolsByTeam{Team: t})
				poolsByTeamMap[t] = &poolsByTeam[len(poolsByTeam)-1]
			}
			poolsByTeamMap[t].Pools = append(poolsByTeamMap[t].Pools, p.Name)
		}
	}
	publicPools, err := provision.ListPools(bson.M{"public": true})
	if err != nil {
		return err
	}
	allowedDefault := permission.Check(t, permission.PermPoolUpdate)
	defaultPool := []provision.Pool{}
	if allowedDefault {
		defaultPool, err = provision.ListPools(bson.M{"default": true})
		if err != nil {
			return err
		}
	}
	p := map[string]interface{}{
		"pools_by_team": poolsByTeam,
		"public_pools":  publicPools,
		"default_pool":  defaultPool,
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(p)
}
Exemple #6
0
// title: service instance list
// path: /services/instances
// method: GET
// produce: application/json
// responses:
//   200: List services instances
//   204: No content
//   401: Unauthorized
func serviceInstances(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	appName := r.URL.Query().Get("app")
	contexts := permission.ContextsForPermission(t, permission.PermServiceInstanceRead)
	instances, err := readableInstances(t, contexts, appName, "")
	if err != nil {
		return err
	}
	contexts = permission.ContextsForPermission(t, permission.PermServiceRead)
	services, err := readableServices(t, contexts)
	if err != nil {
		return err
	}
	servicesMap := map[string]*service.ServiceModel{}
	for _, s := range services {
		if _, in := servicesMap[s.Name]; !in {
			servicesMap[s.Name] = &service.ServiceModel{
				Service:   s.Name,
				Instances: []string{},
			}
		}
	}
	for _, instance := range instances {
		entry := servicesMap[instance.ServiceName]
		if entry == nil {
			continue
		}
		entry.Instances = append(entry.Instances, instance.Name)
		entry.Plans = append(entry.Plans, instance.PlanName)
	}
	result := []service.ServiceModel{}
	for _, entry := range servicesMap {
		result = append(result, *entry)
	}
	if len(result) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(result)
}
Exemple #7
0
// title: service info
// path: /services/{name}
// method: GET
// produce: application/json
// responses:
//   200: OK
func serviceInfo(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	serviceName := r.URL.Query().Get(":name")
	_, err := getService(serviceName)
	if err != nil {
		return err
	}
	contexts := permission.ContextsForPermission(t, permission.PermServiceInstanceRead)
	instances, err := readableInstances(t, contexts, "", serviceName)
	if err != nil {
		return err
	}
	return json.NewEncoder(w).Encode(instances)
}
Exemple #8
0
// title: service list
// path: /services
// method: GET
// produce: application/json
// responses:
//   200: List services
//   204: No content
//   401: Unauthorized
func serviceList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	rec.Log(t.GetUserName(), "list-services")
	teams := []string{}
	serviceNames := []string{}
	contexts := permission.ContextsForPermission(t, permission.PermServiceRead)
	for _, c := range contexts {
		if c.CtxType == permission.CtxGlobal {
			teams = nil
			serviceNames = nil
			break
		}
		switch c.CtxType {
		case permission.CtxService:
			serviceNames = append(serviceNames, c.Value)
		case permission.CtxTeam:
			teams = append(teams, c.Value)
		}
	}
	services, err := service.GetServicesByOwnerTeamsAndServices(teams, serviceNames)
	if err != nil {
		return err
	}
	sInstances, err := service.GetServiceInstancesByServices(services)
	if err != nil {
		return err
	}
	results := make([]service.ServiceModel, len(services))
	for i, s := range services {
		results[i].Service = s.Name
		for _, si := range sInstances {
			if si.ServiceName == s.Name {
				results[i].Instances = append(results[i].Instances, si.Name)
			}
		}
	}
	if len(results) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	b, err := json.Marshal(results)
	if err != nil {
		return &errors.HTTP{Code: http.StatusInternalServerError, Message: err.Error()}
	}
	n, err := w.Write(b)
	if n != len(b) {
		return &errors.HTTP{Code: http.StatusInternalServerError, Message: "Failed to write response body"}
	}
	w.Header().Set("Content-Type", "application/json")
	return err
}
Exemple #9
0
func listContextValues(t permission.Token, scheme *permission.PermissionScheme, failIfEmpty bool) ([]string, error) {
	contexts := permission.ContextsForPermission(t, scheme)
	if len(contexts) == 0 && failIfEmpty {
		return nil, permission.ErrUnauthorized
	}
	values := make([]string, 0, len(contexts))
	for _, ctx := range contexts {
		if ctx.CtxType == permission.CtxGlobal {
			return nil, nil
		}
		values = append(values, ctx.Value)
	}
	return values, nil
}
Exemple #10
0
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 = yaml.Unmarshal(body, &sy)
	if err != nil {
		return err
	}
	teamContexts := permission.ContextsForPermission(t, permission.PermServiceCreate, permission.CtxTeam)
	if sy.Team == "" && len(teamContexts) == 1 {
		sy.Team = teamContexts[0].Value
	}
	err = sy.validate()
	if err != nil {
		return err
	}
	if sy.Team == "" {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: "You must provide a team responsible for this service in the manifest file."}
	}
	allowed := permission.Check(t, permission.PermServiceCreate,
		permission.Context(permission.CtxTeam, sy.Team),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	rec.Log(t.GetUserName(), "create-service", sy.Id, sy.Endpoint)
	s := service.Service{
		Name:       sy.Id,
		Username:   sy.Username,
		Endpoint:   sy.Endpoint,
		Password:   sy.Password,
		OwnerTeams: []string{sy.Team},
	}
	err = s.Create()
	if err != nil {
		httpError := http.StatusInternalServerError
		if err == service.ErrServiceAlreadyExists {
			httpError = http.StatusConflict
		}
		return &errors.HTTP{Code: httpError, Message: err.Error()}
	}
	fmt.Fprint(w, "success")
	return nil
}
Exemple #11
0
// title: app list
// path: /apps
// method: GET
// produce: application/json
// responses:
//   200: List apps
//   204: No content
//   401: Unauthorized
func appList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	filter := &app.Filter{}
	if name := r.URL.Query().Get("name"); name != "" {
		filter.NameMatches = name
	}
	if platform := r.URL.Query().Get("platform"); platform != "" {
		filter.Platform = platform
	}
	if teamOwner := r.URL.Query().Get("teamOwner"); teamOwner != "" {
		filter.TeamOwner = teamOwner
	}
	if owner := r.URL.Query().Get("owner"); owner != "" {
		filter.UserOwner = owner
	}
	if pool := r.URL.Query().Get("pool"); pool != "" {
		filter.Pool = pool
	}
	locked, _ := strconv.ParseBool(r.URL.Query().Get("locked"))
	if locked {
		filter.Locked = true
	}
	if status, ok := r.URL.Query()["status"]; ok {
		filter.Statuses = status
	}
	contexts := permission.ContextsForPermission(t, permission.PermAppRead)
	if len(contexts) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	apps, err := app.List(appFilterByContext(contexts, filter))
	if err != nil {
		return err
	}
	if len(apps) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Set("Content-Type", "application/json")
	miniApps := make([]miniApp, len(apps))
	for i, app := range apps {
		miniApps[i], err = minifyApp(app)
		if err != nil {
			return err
		}
	}
	return json.NewEncoder(w).Encode(miniApps)
}
Exemple #12
0
func readableServices(t auth.Token) ([]service.Service, error) {
	teams := []string{}
	serviceNames := []string{}
	contexts := permission.ContextsForPermission(t, permission.PermServiceRead)
	for _, c := range contexts {
		if c.CtxType == permission.CtxGlobal {
			teams = nil
			serviceNames = nil
			break
		}
		switch c.CtxType {
		case permission.CtxService:
			serviceNames = append(serviceNames, c.Value)
		case permission.CtxTeam:
			teams = append(teams, c.Value)
		}
	}
	return service.GetServicesByTeamsAndServices(teams, serviceNames)
}
Exemple #13
0
func deploysList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	contexts := permission.ContextsForPermission(t, permission.PermAppReadDeploy)
	if len(contexts) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	filter := appFilterByContext(contexts, nil)
	filter.Name = r.URL.Query().Get("app")
	skip := r.URL.Query().Get("skip")
	limit := r.URL.Query().Get("limit")
	skipInt, _ := strconv.Atoi(skip)
	limitInt, _ := strconv.Atoi(limit)
	deploys, err := app.ListDeploys(filter, skipInt, limitInt)
	if err != nil {
		return err
	}
	if len(deploys) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	return json.NewEncoder(w).Encode(deploys)
}
Exemple #14
0
func readableInstances(t auth.Token, appName, serviceName string) ([]service.ServiceInstance, error) {
	teams := []string{}
	instanceNames := []string{}
	contexts := permission.ContextsForPermission(t, permission.PermServiceInstanceRead)
	for _, c := range contexts {
		if c.CtxType == permission.CtxGlobal {
			teams = nil
			instanceNames = nil
			break
		}
		switch c.CtxType {
		case permission.CtxServiceInstance:
			parts := strings.SplitAfterN(c.Value, "/", 2)
			if len(parts) == 2 && parts[0] == serviceName {
				instanceNames = append(instanceNames, parts[1])
			}
		case permission.CtxTeam:
			teams = append(teams, c.Value)
		}
	}
	return service.GetServicesInstancesByTeamsAndNames(teams, instanceNames, appName, serviceName)
}
Exemple #15
0
// title: pool list
// path: /pools
// method: GET
// produce: application/json
// responses:
//   200: OK
//   204: No content
//   401: Unauthorized
//   404: User not found
func poolList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	teams := []string{}
	contexts := permission.ContextsForPermission(t, permission.PermAppCreate)
	for _, c := range contexts {
		if c.CtxType == permission.CtxGlobal {
			teams = nil
			break
		}
		if c.CtxType != permission.CtxTeam {
			continue
		}
		teams = append(teams, c.Value)
	}
	pools, err := provision.ListPossiblePools(teams)
	if err != nil {
		return err
	}
	if len(pools) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(pools)
}
Exemple #16
0
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
	}
	teamContexts := permission.ContextsForPermission(t, permission.PermAppCreate, permission.CtxTeam)
	if a.TeamOwner == "" && len(teamContexts) == 1 {
		a.TeamOwner = teamContexts[0].Value
	}
	canCreate := permission.Check(t, permission.PermAppCreate,
		permission.Context(permission.CtxTeam, a.TeamOwner),
	)
	if !canCreate {
		return permission.ErrUnauthorized
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	platform, err := app.GetPlatform(a.Platform)
	if err != nil {
		return err
	}
	if platform.Disabled {
		canUsePlat := permission.Check(t, permission.PermPlatformUpdate) ||
			permission.Check(t, permission.PermPlatformCreate)
		if !canUsePlat {
			return app.InvalidPlatformError{}
		}
	}
	rec.Log(u.Email, "create-app", "app="+a.Name, "platform="+a.Platform, "plan="+a.Plan.Name)
	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",
				}
			}
		}
		if e, ok := err.(app.InvalidPlatformError); ok {
			return &errors.HTTP{Code: http.StatusNotFound, Message: e.Error()}
		}
		return err
	}
	repo, _ := repository.Manager().GetRepository(a.Name)
	msg := map[string]string{
		"status":         "success",
		"repository_url": repo.ReadWriteURL,
		"ip":             a.Ip,
	}
	jsonMsg, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	fmt.Fprintf(w, "%s", jsonMsg)
	return nil
}
Exemple #17
0
func createServiceInstance(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	var body map[string]string
	err = json.Unmarshal(b, &body)
	if err != nil {
		return err
	}
	serviceName := body["service_name"]
	user, err := t.User()
	if err != nil {
		return err
	}
	srv, err := getService(serviceName)
	if err != nil {
		return err
	}
	instance := service.ServiceInstance{
		Name:      body["name"],
		PlanName:  body["plan"],
		TeamOwner: body["owner"],
	}
	if instance.TeamOwner == "" {
		allContexts := permission.ContextsForPermission(t, permission.PermServiceInstanceCreate)
		teams := make([]string, 0, len(allContexts))
		for _, ctx := range allContexts {
			if ctx.CtxType == permission.CtxGlobal {
				teams = nil
				break
			}
			if ctx.CtxType == permission.CtxTeam {
				teams = append(teams, ctx.Value)
			}
		}
		if teams != nil && len(teams) == 0 {
			return permission.ErrUnauthorized
		}
		if len(teams) == 1 {
			instance.TeamOwner = teams[0]
		}
	}
	if instance.TeamOwner == "" {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: "You must provide a team to create this service instance."}
	}
	allowed := permission.Check(t, permission.PermServiceInstanceCreate,
		permission.Context(permission.CtxTeam, instance.TeamOwner),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	if srv.IsRestricted {
		allowed := permission.Check(t, permission.PermServiceRead,
			append(permission.Contexts(permission.CtxTeam, srv.Teams),
				permission.Context(permission.CtxService, srv.Name))...,
		)
		if !allowed {
			return permission.ErrUnauthorized
		}
	}
	rec.Log(user.Email, "create-service-instance", string(b))
	return service.CreateServiceInstance(instance, &srv, user)
}