// handlePostDashboardCell creates a dashboard cell.
770489
func (h *DashboardHandler) handlePostDashboardCell(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	req, err := decodePostDashboardCellRequest(ctx, r)
	if err != nil {
		EncodeError(ctx, err, w)
		return
	}
	if err := h.DashboardService.AddDashboardCell(ctx, req.dashboardID, req.cell, req.opts); err != nil {
		EncodeError(ctx, err, w)
		return
	}

	if err := encodeResponse(ctx, w, http.StatusCreated, newDashboardCellResponse(req.dashboardID, req.cell)); err != nil {
		logEncodingError(h.Logger, r, err)
		return
	}
}
1123631
func (s *Service) FindDashboardByID(ctx context.Context, id influxdb.ID) (*influxdb.Dashboard, error) {
	var d *influxdb.Dashboard

	err := s.kv.View(ctx, func(tx Tx) error {
		dash, err := s.findDashboardByID(ctx, tx, id)
		if err != nil {
			return err
		}
		d = dash
		return nil
	})

	if err != nil {
		return nil, &influxdb.Error{
			Err: err,
		}
	}

	return d, nil
}
766445
func (c *Client) UpdateDashboardCellView(ctx context.Context, dashboardID, cellID platform.ID, upd platform.ViewUpdate) (*platform.View, error) {
	var v *platform.View

	err := c.db.Update(func(tx *bolt.Tx) error {
		view, err := c.findDashboardCellView(ctx, tx, dashboardID, cellID)
		if err != nil {
			return err
		}

		if err := upd.Apply(view); err != nil {
			return err
		}

		if err := c.putDashboardCellView(ctx, tx, dashboardID, cellID, view); err != nil {
			return err
		}

		v = view
		return nil
	})

	if err != nil {
		return nil, &platform.Error{
			Err: err,
			Op:  getOp(platform.OpUpdateDashboardCellView),
		}
	}

	return v, nil
}
1033424
func UnprovisionDashboard(cmd *models.UnprovisionDashboardCommand) error {
	if _, err := x.Where("dashboard_id = ?", cmd.Id).Delete(&models.DashboardProvisioning{}); err != nil {
		return err
	}
	return nil
}
928261
func (c *Client) PutDashboard(ctx context.Context, d *platform.Dashboard) error {
	return c.db.Update(func(tx *bolt.Tx) error {
		for _, cell := range d.Cells {
			if err := c.createCellView(ctx, tx, d.ID, cell.ID, nil); err != nil {
				return err
			}
		}

		if err := c.putOrganizationDashboardIndex(ctx, tx, d); err != nil {
			return err
		}

		return c.putDashboard(ctx, tx, d)
	})
}
414520
func (s *Service) AddDashboardCell(ctx context.Context, id influxdb.ID, cell *influxdb.Cell, opts influxdb.AddDashboardCellOptions) error {
	err := s.kv.Update(ctx, func(tx Tx) error {
		return s.addDashboardCell(ctx, tx, id, cell, opts)
	})
	if err != nil {
		return &influxdb.Error{
			Err: err,
		}
	}
	return nil
}
222686
func (s *Service) NewDashboardCell(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	dash, err := s.Store.Dashboards(ctx).Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}
	var cell chronograf.DashboardCell
	if err := json.NewDecoder(r.Body).Decode(&cell); err != nil {
		invalidJSON(w, s.Logger)
		return
	}

	if err := ValidDashboardCellRequest(&cell); err != nil {
		invalidData(w, err, s.Logger)
		return
	}

	ids := &idgen.UUID{}
	cid, err := ids.Generate()
	if err != nil {
		msg := fmt.Sprintf("Error creating cell ID of dashboard %d: %v", id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}
	cell.ID = cid

	dash.Cells = append(dash.Cells, cell)
	if err := s.Store.Dashboards(ctx).Update(ctx, dash); err != nil {
		msg := fmt.Sprintf("Error adding cell %s to dashboard %d: %v", cid, id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	boards := newDashboardResponse(dash)
	for _, cell := range boards.Cells {
		if cell.ID == cid {
			encodeJSON(w, http.StatusOK, cell, s.Logger)
			return
		}
	}
}
517959
func (s *Service) DeleteDashboard(ctx context.Context, id platform.ID) error {
	op := OpPrefix + platform.OpDeleteDashboard
	if _, err := s.FindDashboardByID(ctx, id); err != nil {
		return &platform.Error{
			Err: err,
			Op:  op,
		}
	}
	s.dashboardKV.Delete(id.String())
	err := s.deleteLabel(ctx, platform.LabelFilter{ResourceID: id})
	if err != nil {
		return &platform.Error{
			Err: err,
			Op:  op,
		}
	}
	return nil
}
293145
func (dr *dashboardServiceImpl) UnprovisionDashboard(dashboardId int64) error {
	cmd := &models.UnprovisionDashboardCommand{Id: dashboardId}
	return bus.Dispatch(cmd)
}
423139
func checkDashboard(client *sshClient, network string) (*dashboardInfos, error) {
	// Inspect a possible ethstats container on the host
	infos, err := inspectContainer(client, fmt.Sprintf("%s_dashboard_1", network))
	if err != nil {
		return nil, err
	}
	if !infos.running {
		return nil, ErrServiceOffline
	}
	// Resolve the port from the host, or the reverse proxy
	port := infos.portmap["80/tcp"]
	if port == 0 {
		if proxy, _ := checkNginx(client, network); proxy != nil {
			port = proxy.port
		}
	}
	if port == 0 {
		return nil, ErrNotExposed
	}
	// Resolve the host from the reverse-proxy and configure the connection string
	host := infos.envvars["VIRTUAL_HOST"]
	if host == "" {
		host = client.server
	}
	// Run a sanity check to see if the port is reachable
	if err = checkPort(host, port); err != nil {
		log.Warn("Dashboard service seems unreachable", "server", host, "port", port, "err", err)
	}
	// Container available, assemble and return the useful infos
	return &dashboardInfos{
		host:     host,
		port:     port,
		ethstats: infos.envvars["ETHSTATS_PAGE"],
		explorer: infos.envvars["EXPLORER_PAGE"],
		wallet:   infos.envvars["WALLET_PAGE"],
		faucet:   infos.envvars["FAUCET_PAGE"],
	}, nil
}
229787
func (h *DashboardHandler) handleDeleteDashboard(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	req, err := decodeDeleteDashboardRequest(ctx, r)
	if err != nil {
		EncodeError(ctx, err, w)
		return
	}

	if err := h.DashboardService.DeleteDashboard(ctx, req.DashboardID); err != nil {
		EncodeError(ctx, err, w)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}
1156624
func (s *Service) RemoveDashboardCell(ctx context.Context, dashboardID, cellID influxdb.ID) error {
	return s.kv.Update(ctx, func(tx Tx) error {
		d, err := s.findDashboardByID(ctx, tx, dashboardID)
		if err != nil {
			return &influxdb.Error{
				Err: err,
			}
		}

		idx := -1
		for i, cell := range d.Cells {
			if cell.ID == cellID {
				idx = i
				break
			}
		}
		if idx == -1 {
			return &influxdb.Error{
				Code: influxdb.ENotFound,
				Msg:  influxdb.ErrCellNotFound,
			}
		}

		if err := s.deleteDashboardCellView(ctx, tx, d.ID, d.Cells[idx].ID); err != nil {
			return &influxdb.Error{
				Err: err,
			}
		}

		d.Cells = append(d.Cells[:idx], d.Cells[idx+1:]...)

		if err := s.appendDashboardEventToLog(ctx, tx, d.ID, dashboardCellRemovedEvent); err != nil {
			return &influxdb.Error{
				Err: err,
			}
		}

		if err := s.putDashboardWithMeta(ctx, tx, d); err != nil {
			return &influxdb.Error{
				Err: err,
			}
		}
		return nil
	})
}
915558
func (h *DashboardHandler) handleGetDashboards(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	req, err := decodeGetDashboardsRequest(ctx, r)
	if err != nil {
		EncodeError(ctx, err, w)
		return
	}

	if req.ownerID != nil {
		filter := platform.UserResourceMappingFilter{
			UserID:       *req.ownerID,
			UserType:     platform.Owner,
			ResourceType: platform.DashboardsResourceType,
		}

		mappings, _, err := h.UserResourceMappingService.FindUserResourceMappings(ctx, filter)
		if err != nil {
			EncodeError(ctx, &platform.Error{
				Code: platform.EInternal,
				Msg:  "Error loading dashboard owners",
				Err:  err,
			}, w)
			return
		}

		for _, mapping := range mappings {
			req.filter.IDs = append(req.filter.IDs, &mapping.ResourceID)
		}
	}

	dashboards, _, err := h.DashboardService.FindDashboards(ctx, req.filter, req.opts)
	if err != nil {
		EncodeError(ctx, err, w)
		return
	}

	if err := encodeResponse(ctx, w, http.StatusOK, newGetDashboardsResponse(ctx, dashboards, req.filter, req.opts, h.LabelService)); err != nil {
		logEncodingError(h.Logger, r, err)
		return
	}
}
973545
func (s *Service) FindDashboards(ctx context.Context, filter platform.DashboardFilter, opts platform.FindOptions) ([]*platform.Dashboard, int, error) {
	var ds []*platform.Dashboard
	op := OpPrefix + platform.OpFindDashboards
	if len(filter.IDs) == 1 {
		d, err := s.FindDashboardByID(ctx, *filter.IDs[0])
		if err != nil && platform.ErrorCode(err) != platform.ENotFound {
			return ds, 0, &platform.Error{
				Err: err,
				Op:  op,
			}
		}
		if d == nil {
			return ds, 0, nil
		}
		return []*platform.Dashboard{d}, 1, nil
	}

	var count int
	filterFn := filterDashboardFn(filter)
	err := s.forEachDashboard(ctx, opts, func(d *platform.Dashboard) bool {
		if filterFn(d) {
			if count >= opts.Offset {
				ds = append(ds, d)
			}
			count++
		}
		if opts.Limit > 0 && len(ds) >= opts.Limit {
			return false
		}
		return true
	})

	if err != nil {
		return nil, 0, err
	}

	return ds, len(ds), err
}
187072
func (w *wizard) deployDashboard() {
	// Select the server to interact with
	server := w.selectServer()
	if server == "" {
		return
	}
	client := w.servers[server]

	// Retrieve any active dashboard configurations from the server
	infos, err := checkDashboard(client, w.network)
	if err != nil {
		infos = &dashboardInfos{
			port: 80,
			host: client.server,
		}
	}
	existed := err == nil

	// Figure out which port to listen on
	fmt.Println()
	fmt.Printf("Which port should the dashboard listen on? (default = %d)\n", infos.port)
	infos.port = w.readDefaultInt(infos.port)

	// Figure which virtual-host to deploy the dashboard on
	infos.host, err = w.ensureVirtualHost(client, infos.port, infos.host)
	if err != nil {
		log.Error("Failed to decide on dashboard host", "err", err)
		return
	}
	// Port and proxy settings retrieved, figure out which services are available
	available := make(map[string][]string)
	for server, services := range w.services {
		for _, service := range services {
			available[service] = append(available[service], server)
		}
	}
	for _, service := range []string{"ethstats", "explorer", "wallet", "faucet"} {
		// Gather all the locally hosted pages of this type
		var pages []string
		for _, server := range available[service] {
			client := w.servers[server]
			if client == nil {
				continue
			}
			// If there's a service running on the machine, retrieve it's port number
			var port int
			switch service {
			case "ethstats":
				if infos, err := checkEthstats(client, w.network); err == nil {
					port = infos.port
				}
			case "explorer":
				if infos, err := checkExplorer(client, w.network); err == nil {
					port = infos.webPort
				}
			case "wallet":
				if infos, err := checkWallet(client, w.network); err == nil {
					port = infos.webPort
				}
			case "faucet":
				if infos, err := checkFaucet(client, w.network); err == nil {
					port = infos.port
				}
			}
			if page, err := resolve(client, w.network, service, port); err == nil && page != "" {
				pages = append(pages, page)
			}
		}
		// Prompt the user to chose one, enter manually or simply not list this service
		defLabel, defChoice := "don't list", len(pages)+2
		if len(pages) > 0 {
			defLabel, defChoice = pages[0], 1
		}
		fmt.Println()
		fmt.Printf("Which %s service to list? (default = %s)\n", service, defLabel)
		for i, page := range pages {
			fmt.Printf(" %d. %s\n", i+1, page)
		}
		fmt.Printf(" %d. List external %s service\n", len(pages)+1, service)
		fmt.Printf(" %d. Don't list any %s service\n", len(pages)+2, service)

		choice := w.readDefaultInt(defChoice)
		if choice < 0 || choice > len(pages)+2 {
			log.Error("Invalid listing choice, aborting")
			return
		}
		var page string
		switch {
		case choice <= len(pages):
			page = pages[choice-1]
		case choice == len(pages)+1:
			fmt.Println()
			fmt.Printf("Which address is the external %s service at?\n", service)
			page = w.readString()
		default:
			// No service hosting for this
		}
		// Save the users choice
		switch service {
		case "ethstats":
			infos.ethstats = page
		case "explorer":
			infos.explorer = page
		case "wallet":
			infos.wallet = page
		case "faucet":
			infos.faucet = page
		}
	}
	// If we have ethstats running, ask whether to make the secret public or not
	if w.conf.ethstats != "" {
		fmt.Println()
		fmt.Println("Include ethstats secret on dashboard (y/n)? (default = yes)")
		infos.trusted = w.readDefaultYesNo(true)
	}
	// Try to deploy the dashboard container on the host
	nocache := false
	if existed {
		fmt.Println()
		fmt.Printf("Should the dashboard be built from scratch (y/n)? (default = no)\n")
		nocache = w.readDefaultYesNo(false)
	}
	if out, err := deployDashboard(client, w.network, &w.conf, infos, nocache); err != nil {
		log.Error("Failed to deploy dashboard container", "err", err)
		if len(out) > 0 {
			fmt.Printf("%s\n", out)
		}
		return
	}
	// All ok, run a network scan to pick any changes up
	w.networkStats()
}
984721
func (s *Service) FindDashboardByID(ctx context.Context, id platform.ID) (*platform.Dashboard, error) {
	d, pe := s.loadDashboard(ctx, id)
	if pe != nil {
		return nil, &platform.Error{
			Op:  OpPrefix + platform.OpFindDashboardByID,
			Err: pe,
		}
	}
	return d, nil
}
874186
func (s *DashboardEntry) SetDashboardArn(v string) *DashboardEntry {
	s.DashboardArn = &v
	return s
}