MCPcopy Create free account
hub / github.com/bytebase/bytebase / UpdatePlan

Method UpdatePlan

backend/api/v1/plan_service.go:231–436  ·  view source on GitHub ↗

UpdatePlan updates a plan.

(ctx context.Context, request *connect.Request[v1pb.UpdatePlanRequest])

Source from the content-addressed store, hash-verified

229
230// UpdatePlan updates a plan.
231func (s *PlanService) UpdatePlan(ctx context.Context, request *connect.Request[v1pb.UpdatePlanRequest]) (*connect.Response[v1pb.Plan], error) {
232 req := request.Msg
233 if req.UpdateMask == nil {
234 return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("update_mask must be set"))
235 }
236 if len(req.UpdateMask.Paths) == 0 {
237 return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("update_mask must not be empty"))
238 }
239 user, ok := GetUserFromContext(ctx)
240 if !ok {
241 return nil, connect.NewError(connect.CodeInternal, errors.Errorf("user not found"))
242 }
243 projectID, planID, err := common.GetProjectIDPlanID(req.Plan.Name)
244 if err != nil {
245 return nil, connect.NewError(connect.CodeInternal, err)
246 }
247 project, err := s.store.GetProject(ctx, &store.FindProjectMessage{Workspace: common.GetWorkspaceIDFromContext(ctx), ResourceID: &projectID})
248 if err != nil {
249 return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to get project %q, err: %v", projectID, err))
250 }
251 if project == nil {
252 return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("project %q not found", projectID))
253 }
254 oldPlan, err := s.store.GetPlan(ctx, &store.FindPlanMessage{Workspace: common.GetWorkspaceIDFromContext(ctx), ProjectID: projectID, UID: &planID})
255 if err != nil {
256 return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to get plan %q: %v", req.Plan.Name, err))
257 }
258 if oldPlan == nil {
259 if req.AllowMissing {
260 ok, err := s.iamManager.CheckPermission(ctx, permission.PlansCreate, user, common.GetWorkspaceIDFromContext(ctx), projectID)
261 if err != nil {
262 return nil, connect.NewError(connect.CodeInternal, errors.Wrap(err, "failed to check permission"))
263 }
264 if !ok {
265 return nil, connect.NewError(connect.CodePermissionDenied, errors.Errorf("user does not have permission %q", permission.PlansCreate))
266 }
267 return s.CreatePlan(ctx, connect.NewRequest(&v1pb.CreatePlanRequest{
268 Parent: common.FormatProject(projectID),
269 Plan: req.Plan,
270 }))
271 }
272 return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("plan %q not found", req.Plan.Name))
273 }
274
275 if storePlanConfigHasRelease(oldPlan.Config) && slices.Contains(req.UpdateMask.Paths, "specs") {
276 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("disallowed to update the plan specs because the plan is created from a release"))
277 }
278
279 // Disallow updating CREATE_DATABASE plan specs
280 if storePlanConfigHasCreateDatabase(oldPlan.Config) && slices.Contains(req.UpdateMask.Paths, "specs") {
281 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("disallowed to update the plan specs for CREATE_DATABASE plans"))
282 }
283
284 ok, err = func() (bool, error) {
285 if oldPlan.Creator == user.Email {
286 return true, nil
287 }
288 return s.iamManager.CheckPermission(ctx, permission.PlansUpdate, user, common.GetWorkspaceIDFromContext(ctx), oldPlan.ProjectID)

Callers

nothing calls this directly

Calls 15

CreatePlanMethod · 0.95
GetProjectIDPlanIDFunction · 0.92
FormatProjectFunction · 0.92
BBErrorFunction · 0.92
GetUserFromContextFunction · 0.85
validateSpecsFunction · 0.85
convertPlanSpecsFunction · 0.85
planSpecsEqualSetFunction · 0.85

Tested by

no test coverage detected