| OLD | NEW |
| 1 // Copyright 2015 The LUCI Authors. | 1 // Copyright 2015 The LUCI Authors. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // specified by catalog.Definition struct. UpdateProjectJobs skips updates for | 345 // specified by catalog.Definition struct. UpdateProjectJobs skips updates for |
| 346 // such jobs (assuming they are up-to-date). | 346 // such jobs (assuming they are up-to-date). |
| 347 func (e *Job) matches(def catalog.Definition) bool { | 347 func (e *Job) matches(def catalog.Definition) bool { |
| 348 return e.JobID == def.JobID && | 348 return e.JobID == def.JobID && |
| 349 e.Flavor == def.Flavor && | 349 e.Flavor == def.Flavor && |
| 350 e.Schedule == def.Schedule && | 350 e.Schedule == def.Schedule && |
| 351 e.Acls.Equal(&def.Acls) && | 351 e.Acls.Equal(&def.Acls) && |
| 352 bytes.Equal(e.Task, def.Task) | 352 bytes.Equal(e.Task, def.Task) |
| 353 } | 353 } |
| 354 | 354 |
| 355 // isVisible checks if current identity has READER access to this job. |
| 356 func (e *Job) isVisible(c context.Context) (bool, error) { |
| 357 return e.Acls.IsReader(logging.SetField(c, "JobID", e.JobID)) |
| 358 } |
| 359 |
| 360 // isOwned checks if current identity has OWNER access to this job. |
| 361 func (e *Job) isOwned(c context.Context) (bool, error) { |
| 362 return e.Acls.IsOwner(logging.SetField(c, "JobID", e.JobID)) |
| 363 } |
| 364 |
| 355 // Invocation entity stores single attempt to run a job. Its parent entity | 365 // Invocation entity stores single attempt to run a job. Its parent entity |
| 356 // is corresponding Job, its ID is generated based on time. | 366 // is corresponding Job, its ID is generated based on time. |
| 357 type Invocation struct { | 367 type Invocation struct { |
| 358 _kind string `gae:"$kind,Invocation"` | 368 _kind string `gae:"$kind,Invocation"` |
| 359 _extra ds.PropertyMap `gae:"-,extra"` | 369 _extra ds.PropertyMap `gae:"-,extra"` |
| 360 | 370 |
| 361 // ID is identifier of this particular attempt to run a job. Multiple at
tempts | 371 // ID is identifier of this particular attempt to run a job. Multiple at
tempts |
| 362 // to start an invocation result in multiple entities with different IDs
, but | 372 // to start an invocation result in multiple entities with different IDs
, but |
| 363 // with same InvocationNonce. | 373 // with same InvocationNonce. |
| 364 ID int64 `gae:"$id"` | 374 ID int64 `gae:"$id"` |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 return nil, transient.Tag.Apply(err) | 667 return nil, transient.Tag.Apply(err) |
| 658 } | 668 } |
| 659 // Non-ancestor query used, need to recheck filters. | 669 // Non-ancestor query used, need to recheck filters. |
| 660 filtered := make([]*Job, 0, len(entities)) | 670 filtered := make([]*Job, 0, len(entities)) |
| 661 for _, job := range entities { | 671 for _, job := range entities { |
| 662 if !job.Enabled { | 672 if !job.Enabled { |
| 663 continue | 673 continue |
| 664 } | 674 } |
| 665 // TODO(tandrii): improve batch ACLs check here to take advantag
e of likely | 675 // TODO(tandrii): improve batch ACLs check here to take advantag
e of likely |
| 666 // shared ACLs between most jobs of the same project. | 676 // shared ACLs between most jobs of the same project. |
| 667 » » if ok, err := job.Acls.IsReader(c); err != nil { | 677 » » if ok, err := job.isVisible(c); err != nil { |
| 668 return nil, transient.Tag.Apply(err) | 678 return nil, transient.Tag.Apply(err) |
| 669 } else if ok { | 679 } else if ok { |
| 670 filtered = append(filtered, job) | 680 filtered = append(filtered, job) |
| 671 } | 681 } |
| 672 } | 682 } |
| 673 return filtered, nil | 683 return filtered, nil |
| 674 } | 684 } |
| 675 | 685 |
| 676 func (e *engineImpl) GetVisibleJob(c context.Context, jobID string) (*Job, error
) { | 686 func (e *engineImpl) GetVisibleJob(c context.Context, jobID string) (*Job, error
) { |
| 677 job, err := e.getJob(c, jobID) | 687 job, err := e.getJob(c, jobID) |
| 678 if err != nil { | 688 if err != nil { |
| 679 return nil, err | 689 return nil, err |
| 680 } else if job == nil { | 690 } else if job == nil { |
| 681 return nil, ErrNoSuchJob | 691 return nil, ErrNoSuchJob |
| 682 } | 692 } |
| 683 » if ok, err := job.Acls.IsReader(c); err != nil { | 693 » if ok, err := job.isVisible(c); err != nil { |
| 684 return nil, err | 694 return nil, err |
| 685 } else if !ok { | 695 } else if !ok { |
| 686 return nil, ErrNoSuchJob | 696 return nil, ErrNoSuchJob |
| 687 } | 697 } |
| 688 return job, nil | 698 return job, nil |
| 689 } | 699 } |
| 690 | 700 |
| 691 func (e *engineImpl) getOwnedJob(c context.Context, jobID string) (*Job, error)
{ | 701 func (e *engineImpl) getOwnedJob(c context.Context, jobID string) (*Job, error)
{ |
| 692 job, err := e.getJob(c, jobID) | 702 job, err := e.getJob(c, jobID) |
| 693 if err != nil { | 703 if err != nil { |
| 694 return nil, err | 704 return nil, err |
| 695 } else if job == nil { | 705 } else if job == nil { |
| 696 return nil, ErrNoSuchJob | 706 return nil, ErrNoSuchJob |
| 697 } | 707 } |
| 698 | 708 |
| 699 » switch owner, err := job.Acls.IsOwner(c); { | 709 » switch owner, err := job.isOwned(c); { |
| 700 case err != nil: | 710 case err != nil: |
| 701 return nil, err | 711 return nil, err |
| 702 case owner: | 712 case owner: |
| 703 return job, nil | 713 return job, nil |
| 704 } | 714 } |
| 705 | 715 |
| 706 // Not owner, but maybe reader? Give nicer error in such case. | 716 // Not owner, but maybe reader? Give nicer error in such case. |
| 707 » switch reader, err := job.Acls.IsReader(c); { | 717 » switch reader, err := job.isVisible(c); { |
| 708 case err != nil: | 718 case err != nil: |
| 709 return nil, err | 719 return nil, err |
| 710 case reader: | 720 case reader: |
| 711 return nil, ErrNoOwnerPermission | 721 return nil, ErrNoOwnerPermission |
| 712 default: | 722 default: |
| 713 return nil, ErrNoSuchJob | 723 return nil, ErrNoSuchJob |
| 714 } | 724 } |
| 715 } | 725 } |
| 716 | 726 |
| 717 func (e *engineImpl) getJob(c context.Context, jobID string) (*Job, error) { | 727 func (e *engineImpl) getJob(c context.Context, jobID string) (*Job, error) { |
| (...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2072 } | 2082 } |
| 2073 if hasFinished { | 2083 if hasFinished { |
| 2074 return ctl.eng.rollSM(c, job, func(sm *StateMachine) err
or { | 2084 return ctl.eng.rollSM(c, job, func(sm *StateMachine) err
or { |
| 2075 sm.OnInvocationDone(saving.ID) | 2085 sm.OnInvocationDone(saving.ID) |
| 2076 return nil | 2086 return nil |
| 2077 }) | 2087 }) |
| 2078 } | 2088 } |
| 2079 return nil | 2089 return nil |
| 2080 }) | 2090 }) |
| 2081 } | 2091 } |
| OLD | NEW |