go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/led/ledcmd/edit_payload.go (about) 1 // Copyright 2022 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (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 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ledcmd 16 17 import ( 18 "context" 19 20 "github.com/golang/protobuf/jsonpb" 21 22 "go.chromium.org/luci/common/errors" 23 24 swarmingpb "go.chromium.org/luci/swarming/proto/api_v2" 25 26 "go.chromium.org/luci/led/job" 27 ) 28 29 type EditPayloadOpts struct { 30 // PropertyOnly determines whether to pass the recipe bundle's RBE-CAS reference 31 // as a property and preserve the executable and payload of the input job 32 // rather than overwriting it. 33 PropertyOnly bool 34 35 // CasDigest is the digest of the RBE-CAS reference. 36 CasDigest *swarmingpb.Digest 37 38 // CIPDPkg is the name of the CIPD package for the payload. 39 CIPDPkg string 40 // CIPDVer is the version of the CIPD package for the payload. 41 CIPDVer string 42 } 43 44 // editPayloadWithCASRef overrides the job payload with given RBE-CAS reference. 45 func editPayloadWithCASRef(ctx context.Context, jd *job.Definition, opts *EditPayloadOpts) (err error) { 46 casRef := &swarmingpb.CASReference{ 47 Digest: opts.CasDigest, 48 } 49 if casRef.CasInstance, err = getCASInstance(jd); err != nil { 50 return 51 } 52 53 setRecipeBundleProperty := opts.PropertyOnly || jd.GetBuildbucket().GetBbagentArgs().GetBuild().GetInput().GetProperties().GetFields()[job.LEDBuilderIsBootstrappedProperty].GetBoolValue() 54 if setRecipeBundleProperty { 55 m := &jsonpb.Marshaler{OrigName: true} 56 jsonCASRef, err := m.MarshalToString(casRef) 57 if err != nil { 58 return errors.Annotate(err, "encoding CAS user payload").Err() 59 } 60 return jd.HighLevelEdit(func(je job.HighLevelEditor) { 61 je.Properties(map[string]string{ 62 CASRecipeBundleProperty: jsonCASRef, 63 }, false) 64 }) 65 } 66 67 if err = jd.Edit(func(je job.Editor) { 68 je.ClearCurrentIsolated() 69 }); err != nil { 70 return err 71 } 72 if jd.GetSwarming() != nil { 73 jd.GetSwarming().CasUserPayload = casRef 74 return nil 75 } 76 return jd.HighLevelEdit(func(je job.HighLevelEditor) { 77 je.TaskPayloadSource("", "") 78 je.CASTaskPayload(job.RecipeDirectory, casRef) 79 }) 80 } 81 82 // editPayloadWithCIPD overrides the job payload with given CIPD info. 83 func editPayloadWithCIPD(ctx context.Context, jd *job.Definition, opts *EditPayloadOpts) (err error) { 84 setRecipeBundleProperty := opts.PropertyOnly || jd.GetBuildbucket().GetBbagentArgs().GetBuild().GetInput().GetProperties().GetFields()[job.LEDBuilderIsBootstrappedProperty].GetBoolValue() 85 if setRecipeBundleProperty { 86 return errors.Reason("cannot use CIPD info in property-only mode").Err() 87 } 88 89 return jd.HighLevelEdit(func(je job.HighLevelEditor) { 90 pkg, ver := jd.HighLevelInfo().TaskPayloadSource() 91 if opts.CIPDPkg != "" { 92 pkg = opts.CIPDPkg 93 } 94 if opts.CIPDVer != "" { 95 ver = opts.CIPDVer 96 } 97 je.TaskPayloadSource(pkg, ver) 98 }) 99 } 100 101 // EditPayload overrides the payload of the given job with given RBE-CAS or CIPD info. 102 func EditPayload(ctx context.Context, jd *job.Definition, opts *EditPayloadOpts) error { 103 switch { 104 case opts.CasDigest != nil: 105 return editPayloadWithCASRef(ctx, jd, opts) 106 case opts.CIPDPkg != "" || opts.CIPDVer != "": 107 return editPayloadWithCIPD(ctx, jd, opts) 108 } 109 return nil 110 }