func serviceDelete(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	ctx := r.Context()
	s, err := getService(ctx, r.URL.Query().Get(":name"))
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermServiceDelete,
		contextsForServiceProvision(&s)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	evt, err := event.New(&event.Opts{
		Target:     serviceTarget(s.Name),
		Kind:       permission.PermServiceDelete,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermServiceReadEvents, contextsForServiceProvision(&s)...),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	instances, err := service.GetServiceInstancesByServices([]service.Service{s})
	if err != nil {
		return err
	}
	if len(instances) > 0 {
		msg := "This service cannot be removed because it has instances.\n"
		msg += "Please remove these instances before removing the service."
		return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
	}
	return service.Delete(s)
}
title: service delete
path: /services/{name}
method: DELETE
responses:
200: Service removed
401: Unauthorized
403: Forbidden (team is not the owner or service with instances)
404: Service not found
package api
import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"github.com/tsuru/tsuru/auth"
	"github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/event"
	"github.com/tsuru/tsuru/permission"
	"github.com/tsuru/tsuru/service"
	"github.com/tsuru/tsuru/servicemanager"
	authTypes "github.com/tsuru/tsuru/types/auth"
	permTypes "github.com/tsuru/tsuru/types/permission"
)
func serviceTarget(name string) event.Target {
	return event.Target{Type: event.TargetTypeService, Value: name}
}
func provisionReadableServices(ctx context.Context, t auth.Token, contexts []permTypes.PermissionContext) ([]service.Service, error) {
	teams, serviceNames := filtersForServiceList(t, contexts)
	return service.GetServicesByOwnerTeamsAndServices(ctx, teams, serviceNames)
}
func serviceList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	ctx := r.Context()
	contexts := permission.ContextsForPermission(t, permission.PermServiceRead)
	services, err := provisionReadableServices(ctx, 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)
				results[i].ServiceInstances = append(results[i].ServiceInstances, si)
			}
		}
	}
	if len(results) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(results)
}
type serviceInput struct {
	Name      string            `json:"id" form:"id"`
	Username  string            `json:"username" form:"username"`
	Password  string            `json:"password" form:"password"`
	Endpoints map[string]string `json:"endpoints" form:"endpoints"`
	Endpoint  string            `json:"endpoint" form:"endpoint"`
}
func parseService(r *http.Request) (service.Service, error) {
	var s service.Service
	var inputSvc serviceInput
	err := ParseInput(r, &inputSvc)
	if err != nil {
		return s, &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	s.Name = inputSvc.Name
	s.Username = inputSvc.Username
	s.Password = inputSvc.Password
	if len(inputSvc.Endpoints) != 0 {
		s.Endpoint = inputSvc.Endpoints
	} else if inputSvc.Endpoint != "" {
		s.Endpoint = map[string]string{"production": inputSvc.Endpoint}
	}
	multiCluster, err := strconv.ParseBool(InputValue(r, "multi-cluster"))
	if err == nil {
		s.IsMultiCluster = multiCluster
	}
	team := InputValue(r, "team")
	if team != "" {
		s.OwnerTeams = []string{team}
	}
	return s, nil
}
func serviceCreate(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	s, err := parseService(r)
	if err != nil {
		return err
	}
	if len(s.OwnerTeams) == 0 {
		var team string
		team, err = permission.TeamForPermission(t, permission.PermServiceCreate)
		if err == permission.ErrTooManyTeams {
			return &errors.HTTP{
				Code:    http.StatusBadRequest,
				Message: "You must provide a team responsible for this service in the manifest file.",
			}
		}
		if err != nil {
			return err
		}
		s.OwnerTeams = []string{team}
	}
	allowed := permission.Check(t, permission.PermServiceCreate,
		permission.Context(permTypes.CtxTeam, s.OwnerTeams[0]),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	delete(r.Form, "password")
	evt, err := event.New(&event.Opts{
		Target:     serviceTarget(s.Name),
		Kind:       permission.PermServiceCreate,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermServiceReadEvents, contextsForServiceProvision(&s)...),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	err = service.Create(s)
	if err != nil {
		if err == service.ErrServiceAlreadyExists {
			return &errors.HTTP{Code: http.StatusConflict, Message: err.Error()}
		}
		return err
	}
	w.WriteHeader(http.StatusCreated)
	fmt.Fprint(w, "success")
	return nil
}
func serviceUpdate(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	d, err := parseService(r)
	if err != nil {
		return err
	}
	d.Name = r.URL.Query().Get(":name")
	ctx := r.Context()
	s, err := getService(ctx, d.Name)
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermServiceUpdate,
		contextsForServiceProvision(&s)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	delete(r.Form, "password")
	evt, err := event.New(&event.Opts{
		Target:     serviceTarget(s.Name),
		Kind:       permission.PermServiceUpdate,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermServiceReadEvents, contextsForServiceProvision(&s)...),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	s.Endpoint = d.Endpoint
	s.Password = d.Password
	s.Username = d.Username
	if len(d.OwnerTeams) != 0 {
		s.OwnerTeams = d.OwnerTeams
	}
	return service.Update(s)
}