func (api *HTTPAPI) Send(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { volumeID := ps.ByName("volume_id") if !strings.Contains(r.Header.Get("Accept"), snapshotContentType) { httphelper.ValidationError(w, "", fmt.Sprintf("must be prepared to accept a content type of %q", snapshotContentType)) return } w.Header().Set("Content-Type", snapshotContentType) var haves []json.RawMessage if err := httphelper.DecodeJSON(r, &haves); err != nil { httphelper.Error(w, err) return } err := api.vman.SendSnapshot(volumeID, haves, w) if err != nil { switch err { case volume.ErrNoSuchVolume: httphelper.ObjectNotFoundError(w, fmt.Sprintf("no volume with id %q", volumeID)) return default: httphelper.Error(w, err) return } } }
// serveGetLeader returns the current leader for a service. func (h *Handler) serveGetLeader(w http.ResponseWriter, r *http.Request, params httprouter.Params) { // Process as a stream if that's what the client wants. if strings.Contains(r.Header.Get("Accept"), "text/event-stream") { if !h.Store.IsLeader() { h.redirectToLeader(w, r) return } h.serveStream(w, params, discoverd.EventKindLeader) return } // Otherwise retrieve the current leader. service := params.ByName("service") leader, err := h.Store.ServiceLeader(service) if err != nil { hh.Error(w, err) return } else if leader == nil { hh.ObjectNotFoundError(w, "no leader found") return } // Write leader to the response. hh.JSON(w, 200, leader) }
func (api *httpAPI) EventsHandler(w http.ResponseWriter, req *http.Request, params httprouter.Params) { api.InstallerStackMtx.Lock() s := api.InstallerStacks[params.ByName("id")] api.InstallerStackMtx.Unlock() if s == nil { httphelper.ObjectNotFoundError(w, "install instance not found") return } eventChan := make(chan *httpEvent) doneChan, errChan := s.Subscribe(eventChan) stream := sse.NewStream(w, eventChan, s.logger) stream.Serve() s.logger.Info(fmt.Sprintf("streaming events for %s", s.ID)) go func() { for { select { case err := <-errChan: s.logger.Info(err.Error()) stream.Error(err) case <-doneChan: stream.Close() return } } }() stream.Wait() }
func (api *httpAPI) GetCloudRegions(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { params := req.URL.Query() cloud := params.Get("cloud") if cloud != "digital_ocean" && cloud != "azure" { httphelper.ObjectNotFoundError(w, "") return } credentialID := params.Get("credential_id") creds, err := api.Installer.FindCredentials(credentialID) if err != nil { httphelper.ValidationError(w, "credential_id", "Invalid credential id") return } var res interface{} switch cloud { case "digital_ocean": res, err = api.Installer.ListDigitalOceanRegions(creds) case "azure": res, err = api.Installer.ListAzureRegions(creds) } if err != nil { httphelper.Error(w, err) return } httphelper.JSON(w, 200, res) }
// servePutInstance adds an instance to a service. func (h *Handler) servePutInstance(w http.ResponseWriter, r *http.Request, params httprouter.Params) { // Read path parameter. service := params.ByName("service") // Read instance from request. inst := &discoverd.Instance{} if err := json.NewDecoder(r.Body).Decode(inst); err != nil { hh.Error(w, err) return } // Ensure instance is valid. if err := inst.Valid(); err != nil { hh.ValidationError(w, "", err.Error()) return } // Add instance to service in the store. if err := h.Store.AddInstance(service, inst); err == ErrNotLeader { h.redirectToLeader(w, r) return } else if IsNotFound(err) { hh.ObjectNotFoundError(w, err.Error()) return } else if err != nil { hh.Error(w, err) return } }
func (api *httpAPI) ServeTemplate(w http.ResponseWriter, req *http.Request, params httprouter.Params) { if req.Header.Get("Accept") == "application/json" { s, err := api.Installer.FindBaseCluster(params.ByName("id")) if err != nil { httphelper.ObjectNotFoundError(w, err.Error()) return } httphelper.JSON(w, 200, s) return } manifest, err := api.AssetManifest() if err != nil { httphelper.Error(w, err) api.logger.Debug(err.Error()) return } w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Cache-Control", "max-age=0") err = htmlTemplate.Execute(w, &htmlTemplateData{ ApplicationJSPath: manifest.Assets["application.js"], ApplicationCSSPath: manifest.Assets["application.css"], ReactJSPath: manifest.Assets["react.js"], }) if err != nil { httphelper.Error(w, err) api.logger.Debug(err.Error()) return } }
func (h *httpAPI) GetServiceMeta(w http.ResponseWriter, r *http.Request, params httprouter.Params) { meta := h.Store.GetServiceMeta(params.ByName("service")) if meta == nil { hh.ObjectNotFoundError(w, "service meta not found") return } hh.JSON(w, 200, meta) }
func (api *httpAPI) GetCert(w http.ResponseWriter, req *http.Request, params httprouter.Params) { cluster, err := api.Installer.FindBaseCluster(params.ByName("id")) if err != nil { httphelper.ObjectNotFoundError(w, err.Error()) return } w.Header().Set("Content-Type", "application/x-x509-ca-cert") w.Header().Set("Content-Disposition", `attachment; filename="flynn-ca.cer"`) w.Write([]byte(cluster.CACert)) }
func (h *httpAPI) RemoveInstance(w http.ResponseWriter, r *http.Request, params httprouter.Params) { if err := h.Store.RemoveInstance(params.ByName("service"), params.ByName("instance_id")); err != nil { if IsNotFound(err) { hh.ObjectNotFoundError(w, err.Error()) } else { hh.Error(w, err) } return } }
func (api *HTTPAPI) Inspect(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { volumeID := ps.ByName("volume_id") vol := api.vman.GetVolume(volumeID) if vol == nil { httphelper.ObjectNotFoundError(w, fmt.Sprintf("no volume with id %q", volumeID)) return } httphelper.JSON(w, 200, vol.Info()) }
func (api *HTTPAPI) Create(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { providerID := ps.ByName("provider_id") vol, err := api.vman.NewVolumeFromProvider(providerID) if err == volumemanager.NoSuchProvider { httphelper.ObjectNotFoundError(w, fmt.Sprintf("no volume provider with id %q", providerID)) return } httphelper.JSON(w, 200, vol.Info()) }
func (api *httpAPI) Prompt(w http.ResponseWriter, req *http.Request, params httprouter.Params) { s, err := api.Installer.FindBaseCluster(params.ByName("id")) if err != nil { httphelper.ObjectNotFoundError(w, "cluster not found") return } prompt, err := s.findPrompt(params.ByName("prompt_id")) if err != nil { httphelper.ObjectNotFoundError(w, "prompt not found") return } var input *Prompt if err := httphelper.DecodeJSON(req, &input); err != nil { httphelper.Error(w, err) return } prompt.Resolve(input) w.WriteHeader(200) }
func (api *httpAPI) DeleteCluster(w http.ResponseWriter, req *http.Request, params httprouter.Params) { if err := api.Installer.DeleteCluster(params.ByName("id")); err != nil { if err == ClusterNotFoundError { httphelper.ObjectNotFoundError(w, err.Error()) return } httphelper.Error(w, err) return } w.WriteHeader(200) }
func (h *httpAPI) GetLeader(w http.ResponseWriter, r *http.Request, params httprouter.Params) { if strings.Contains(r.Header.Get("Accept"), "text/event-stream") { h.handleStream(w, params, discoverd.EventKindLeader) return } leader := h.Store.GetLeader(params.ByName("service")) if leader == nil { hh.ObjectNotFoundError(w, "no leader found") return } hh.JSON(w, 200, leader) }
func (h *httpAPI) GetInstances(w http.ResponseWriter, r *http.Request, params httprouter.Params) { if strings.Contains(r.Header.Get("Accept"), "text/event-stream") { h.handleStream(w, params, discoverd.EventKindUp|discoverd.EventKindUpdate|discoverd.EventKindDown) return } instances := h.Store.Get(params.ByName("service")) if instances == nil { hh.ObjectNotFoundError(w, "service not found") return } hh.JSON(w, 200, instances) }
// serveGetServiceMeta returns the metadata for a service. func (h *Handler) serveGetServiceMeta(w http.ResponseWriter, r *http.Request, params httprouter.Params) { // Read path parameter. service := params.ByName("service") // Read meta from the store. meta := h.Store.ServiceMeta(service) if meta == nil { hh.ObjectNotFoundError(w, "service meta not found") return } // Write meta to the response. hh.JSON(w, 200, meta) }
func (h *httpAPI) RemoveService(w http.ResponseWriter, r *http.Request, params httprouter.Params) { service := params.ByName("service") if err := ValidServiceName(service); err != nil { hh.ValidationError(w, "", err.Error()) return } if err := h.Store.RemoveService(params.ByName("service")); err != nil { if IsNotFound(err) { hh.ObjectNotFoundError(w, err.Error()) } else { hh.Error(w, err) } return } }
func (api *httpAPI) Prompt(w http.ResponseWriter, req *http.Request, params httprouter.Params) { cluster, err := api.Installer.FindCluster(params.ByName("id")) if err != nil { httphelper.ObjectNotFoundError(w, "cluster not found") return } prompt, err := cluster.Base().findPrompt(params.ByName("prompt_id")) if err != nil { httphelper.ObjectNotFoundError(w, "prompt not found") return } defer req.Body.Close() var input *Prompt if prompt.Type == PromptTypeFile { size, err := strconv.Atoi(req.Header.Get("Content-Length")) if err != nil { httphelper.Error(w, err) return } input = &Prompt{ File: req.Body, FileSize: size, } } else { if err := httphelper.DecodeJSON(req, &input); err != nil { httphelper.Error(w, err) return } } if err := prompt.Resolve(input); err != nil { httphelper.Error(w, err) return } w.WriteHeader(200) }
func (api *HTTPAPI) Destroy(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { volumeID := ps.ByName("volume_id") err := api.vman.DestroyVolume(volumeID) if err != nil { switch err { case volume.ErrNoSuchVolume: httphelper.ObjectNotFoundError(w, fmt.Sprintf("no volume with id %q", volumeID)) return default: httphelper.Error(w, err) return } } w.WriteHeader(200) }
func (api *HTTPAPI) Snapshot(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { volumeID := ps.ByName("volume_id") snap, err := api.vman.CreateSnapshot(volumeID) if err != nil { switch err { case volume.ErrNoSuchVolume: httphelper.ObjectNotFoundError(w, fmt.Sprintf("no volume with id %q", volumeID)) return default: httphelper.Error(w, err) return } } httphelper.JSON(w, 200, snap.Info()) }
func (h *jobAPI) GetJob(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { id := ps.ByName("id") if strings.Contains(r.Header.Get("Accept"), "text/event-stream") { if err := h.host.streamEvents(id, w); err != nil { httphelper.Error(w, err) } return } job := h.host.state.GetJob(id) if job == nil { httphelper.ObjectNotFoundError(w, ErrNotFound.Error()) return } httphelper.JSON(w, 200, job) }
func (api *API) GetCert(ctx context.Context, w http.ResponseWriter, req *http.Request) { params, _ := ctxhelper.ParamsFromContext(ctx) l := api.router.HTTP.(*HTTPListener) cert, err := l.GetCert(params.ByName("id")) if err == ErrNotFound { httphelper.ObjectNotFoundError(w, "certificate not found") return } if err != nil { httphelper.Error(w, err) return } httphelper.JSON(w, 200, cert) }
func (api *httpAPI) PromptHandler(w http.ResponseWriter, req *http.Request, params httprouter.Params) { api.InstallerPromptsMtx.Lock() prompt := api.InstallerPrompts[params.ByName("id")] api.InstallerPromptsMtx.Unlock() if prompt == nil { httphelper.ObjectNotFoundError(w, "prompt not found") return } var input *httpPrompt if err := httphelper.DecodeJSON(req, &input); err != nil { httphelper.Error(w, err) return } prompt.Resolve(input) w.WriteHeader(200) }
// serveDeleteInstance removes an instance from the store by name. func (h *Handler) serveDeleteInstance(w http.ResponseWriter, r *http.Request, params httprouter.Params) { // Retrieve path parameters. service := params.ByName("service") instanceID := params.ByName("instance_id") // Remove instance from the store. if err := h.Store.RemoveInstance(service, instanceID); err == ErrNotLeader { h.redirectToLeader(w, r) return } else if IsNotFound(err) { hh.ObjectNotFoundError(w, err.Error()) return } else if err != nil { hh.Error(w, err) return } }
func (api *API) DeleteCert(ctx context.Context, w http.ResponseWriter, req *http.Request) { params, _ := ctxhelper.ParamsFromContext(ctx) l := api.router.HTTP.(*HTTPListener) err := l.RemoveCert(params.ByName("id")) if err != nil { switch err { case ErrNotFound: httphelper.ObjectNotFoundError(w, "certificate not found") return default: httphelper.Error(w, err) return } } w.WriteHeader(200) }
func (h *httpAPI) SetServiceMeta(w http.ResponseWriter, r *http.Request, params httprouter.Params) { meta := &discoverd.ServiceMeta{} if err := hh.DecodeJSON(r, meta); err != nil { hh.Error(w, err) return } if err := h.Store.SetServiceMeta(params.ByName("service"), meta); err != nil { if IsNotFound(err) { hh.ObjectNotFoundError(w, err.Error()) } else { hh.Error(w, err) } return } hh.JSON(w, 200, meta) }
func (api *httpAPI) ReceiveBackup(w http.ResponseWriter, req *http.Request, params httprouter.Params) { cluster, err := api.Installer.FindBaseCluster(params.ByName("id")) if err != nil { httphelper.ObjectNotFoundError(w, err.Error()) return } defer req.Body.Close() size, err := strconv.Atoi(req.Header.Get("Content-Length")) if err != nil { httphelper.Error(w, err) return } if err := cluster.ReceiveBackup(req.Body, size); err != nil { httphelper.Error(w, err) return } w.WriteHeader(200) }
func (h *httpAPI) AddInstance(w http.ResponseWriter, r *http.Request, params httprouter.Params) { inst := &discoverd.Instance{} if err := json.NewDecoder(r.Body).Decode(inst); err != nil { hh.Error(w, err) return } if err := inst.Valid(); err != nil { hh.ValidationError(w, "", err.Error()) return } if err := h.Store.AddInstance(params.ByName("service"), inst); err != nil { if IsNotFound(err) { hh.ObjectNotFoundError(w, err.Error()) } else { hh.Error(w, err) } return } }
// serveGetInstances returns a list of all instances for a service. func (h *Handler) serveGetInstances(w http.ResponseWriter, r *http.Request, params httprouter.Params) { // If the client is requesting a stream, then handle as a stream. if strings.Contains(r.Header.Get("Accept"), "text/event-stream") { h.serveStream(w, params, discoverd.EventKindUp|discoverd.EventKindUpdate|discoverd.EventKindDown) return } // Otherwise read instances from the store. instances, err := h.Store.Instances(params.ByName("service")) if err != nil { hh.Error(w, err) return } else if instances == nil { hh.ObjectNotFoundError(w, "service not found") return } // Write instances to the response. hh.JSON(w, 200, instances) }
// serveDeleteService removes a service from the store by name. func (h *Handler) serveDeleteService(w http.ResponseWriter, r *http.Request, params httprouter.Params) { // Retrieve the path parameter. service := params.ByName("service") if err := ValidServiceName(service); err != nil { hh.ValidationError(w, "", err.Error()) return } // Delete from the store. if err := h.Store.RemoveService(params.ByName("service")); err == ErrNotLeader { h.redirectToLeader(w, r) return } else if IsNotFound(err) { hh.ObjectNotFoundError(w, err.Error()) return } else if err != nil { hh.Error(w, err) return } }