// title: service instance info // path: /services/{service}/instances/{instance} // method: GET // produce: application/json // responses: // 200: OK // 401: Unauthorized // 404: Service instance not found func serviceInstance(w http.ResponseWriter, r *http.Request, t auth.Token) error { instanceName := r.URL.Query().Get(":instance") serviceName := r.URL.Query().Get(":service") serviceInstance, err := getServiceInstanceOrError(serviceName, instanceName) if err != nil { return err } allowed := permission.Check(t, permission.PermServiceInstanceRead, contextsForServiceInstance(serviceInstance, serviceName)..., ) if !allowed { return permission.ErrUnauthorized } requestIDHeader, _ := config.GetString("request-id-header") requestID := context.GetRequestID(r, requestIDHeader) info, err := serviceInstance.Info(requestID) if err != nil { return err } plan, err := service.GetPlanByServiceNameAndPlanName(serviceName, serviceInstance.PlanName, requestID) if err != nil { return err } sInfo := serviceInstanceInfo{ Apps: serviceInstance.Apps, Teams: serviceInstance.Teams, TeamOwner: serviceInstance.TeamOwner, Description: serviceInstance.Description, PlanName: plan.Name, PlanDescription: plan.Description, CustomInfo: info, } w.Header().Set("Content-Type", "application/json") return json.NewEncoder(w).Encode(sInfo) }
func (s *S) TestSetRequestIDHeaderMiddlewareNoConfig(c *check.C) { config.Unset("request-id-header") rec := httptest.NewRecorder() req, err := http.NewRequest("GET", "/", nil) c.Assert(err, check.IsNil) h, log := doHandler() setRequestIDHeaderMiddleware(rec, req, h) c.Assert(log.called, check.Equals, true) reqID := context.GetRequestID(req, "") c.Assert(reqID, check.Equals, "") }
func (l *loggerMiddleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { start := time.Now() next(rw, r) duration := time.Since(start) statusCode := rw.(negroni.ResponseWriter).Status() if statusCode == 0 { statusCode = 200 } nowFormatted := time.Now().Format(time.RFC3339Nano) requestIDHeader, _ := config.GetString("request-id-header") var requestID string if requestIDHeader != "" { requestID = context.GetRequestID(r, requestIDHeader) if requestID != "" { requestID = fmt.Sprintf(" [%s: %s]", requestIDHeader, requestID) } } l.logger.Printf("%s %s %s %d in %0.6fms%s", nowFormatted, r.Method, r.URL.Path, statusCode, float64(duration)/float64(time.Millisecond), requestID) }
// title: service instance status // path: /services/{service}/instances/{instance}/status // method: GET // responses: // 200: List services instances // 401: Unauthorized // 404: Service instance not found func serviceInstanceStatus(w http.ResponseWriter, r *http.Request, t auth.Token) error { instanceName := r.URL.Query().Get(":instance") serviceName := r.URL.Query().Get(":service") serviceInstance, err := getServiceInstanceOrError(serviceName, instanceName) if err != nil { return err } allowed := permission.Check(t, permission.PermServiceInstanceReadStatus, contextsForServiceInstance(serviceInstance, serviceName)..., ) if !allowed { return permission.ErrUnauthorized } var b string requestIDHeader, _ := config.GetString("request-id-header") requestID := context.GetRequestID(r, requestIDHeader) if b, err = serviceInstance.Status(requestID); err != nil { return errors.Wrap(err, "Could not retrieve status of service instance, error") } _, err = fmt.Fprintf(w, `Service instance "%s" is %s`, instanceName, b) return err }
// title: service plans // path: /services/{name}/plans // method: GET // produce: application/json // responses: // 200: OK // 401: Unauthorized // 404: Service not found func servicePlans(w http.ResponseWriter, r *http.Request, t auth.Token) error { serviceName := r.URL.Query().Get(":name") s, err := getService(serviceName) if err != nil { return err } if s.IsRestricted { allowed := permission.Check(t, permission.PermServiceReadPlans, contextsForService(&s)..., ) if !allowed { return permission.ErrUnauthorized } } requestIDHeader, _ := config.GetString("request-id-header") requestID := context.GetRequestID(r, requestIDHeader) plans, err := service.GetPlansByServiceName(serviceName, requestID) if err != nil { return err } w.Header().Set("Content-Type", "application/json") return json.NewEncoder(w).Encode(plans) }
// title: service instance create // path: /services/{service}/instances // method: POST // consume: application/x-www-form-urlencoded // responses: // 201: Service created // 400: Invalid data // 401: Unauthorized // 409: Service already exists func createServiceInstance(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) { serviceName := r.URL.Query().Get(":service") user, err := t.User() if err != nil { return err } srv, err := getService(serviceName) if err != nil { return err } instance := service.ServiceInstance{ Name: r.FormValue("name"), PlanName: r.FormValue("plan"), TeamOwner: r.FormValue("owner"), Description: r.FormValue("description"), } var teamOwner string if instance.TeamOwner == "" { teamOwner, err = permission.TeamForPermission(t, permission.PermServiceInstanceCreate) if err != nil { return err } instance.TeamOwner = teamOwner } 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, contextsForService(&srv)..., ) if !allowed { return permission.ErrUnauthorized } } evt, err := event.New(&event.Opts{ Target: serviceInstanceTarget(serviceName, instance.Name), Kind: permission.PermServiceInstanceCreate, Owner: t, CustomData: event.FormToCustomData(r.Form), Allowed: event.Allowed(permission.PermServiceInstanceReadEvents, contextsForServiceInstance(&instance, srv.Name)...), }) if err != nil { return err } defer func() { evt.Done(err) }() requestIDHeader, _ := config.GetString("request-id-header") requestID := context.GetRequestID(r, requestIDHeader) err = service.CreateServiceInstance(instance, &srv, user, requestID) if err == service.ErrInstanceNameAlreadyExists { return &tsuruErrors.HTTP{ Code: http.StatusConflict, Message: err.Error(), } } if err == service.ErrInvalidInstanceName { return &tsuruErrors.HTTP{ Code: http.StatusBadRequest, Message: err.Error(), } } if err == nil { w.WriteHeader(http.StatusCreated) } return err }
// title: remove service instance // path: /services/{name}/instances/{instance} // method: DELETE // produce: application/x-json-stream // responses: // 200: Service removed // 401: Unauthorized // 404: Service instance not found func removeServiceInstance(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) { r.ParseForm() unbindAll := r.URL.Query().Get("unbindall") serviceName := r.URL.Query().Get(":service") instanceName := r.URL.Query().Get(":instance") serviceInstance, err := getServiceInstanceOrError(serviceName, instanceName) if err != nil { return err } keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "") defer keepAliveWriter.Stop() writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)} w.Header().Set("Content-Type", "application/x-json-stream") allowed := permission.Check(t, permission.PermServiceInstanceDelete, contextsForServiceInstance(serviceInstance, serviceName)..., ) if !allowed { return permission.ErrUnauthorized } evt, err := event.New(&event.Opts{ Target: serviceInstanceTarget(serviceName, instanceName), Kind: permission.PermServiceInstanceDelete, Owner: t, CustomData: event.FormToCustomData(r.Form), Allowed: event.Allowed(permission.PermServiceInstanceReadEvents, contextsForServiceInstance(serviceInstance, serviceName)...), }) if err != nil { return err } defer func() { evt.Done(err) }() unbindAllBool, _ := strconv.ParseBool(unbindAll) if unbindAllBool { if len(serviceInstance.Apps) > 0 { for _, appName := range serviceInstance.Apps { _, app, instErr := getServiceInstance(serviceInstance.ServiceName, serviceInstance.Name, appName) if instErr != nil { return instErr } fmt.Fprintf(writer, "Unbind app %q ...\n", app.GetName()) instErr = serviceInstance.UnbindApp(app, true, writer) if instErr != nil { return instErr } fmt.Fprintf(writer, "\nInstance %q is not bound to the app %q anymore.\n", serviceInstance.Name, app.GetName()) } serviceInstance, err = getServiceInstanceOrError(serviceName, instanceName) if err != nil { return err } } } requestIDHeader, _ := config.GetString("request-id-header") requestID := context.GetRequestID(r, requestIDHeader) err = service.DeleteInstance(serviceInstance, requestID) if err != nil { if err == service.ErrServiceInstanceBound { writer.Write([]byte(strings.Join(serviceInstance.Apps, ","))) } return err } writer.Write([]byte("service instance successfully removed")) return nil }