Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: vpython/cipd/cipd.go

Issue 2699223002: vpython: Add CIPD support. (Closed)
Patch Set: comments, path => name Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « vpython/api/vpython/spec.pb.go ('k') | vpython/spec/load_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package cipd
6
7 import (
8 "github.com/luci/luci-go/vpython/api/vpython"
9 "github.com/luci/luci-go/vpython/venv"
10
11 "github.com/luci/luci-go/cipd/client/cipd"
12 "github.com/luci/luci-go/cipd/client/cipd/common"
13 "github.com/luci/luci-go/cipd/client/cipd/ensure"
14 "github.com/luci/luci-go/common/errors"
15 "github.com/luci/luci-go/common/logging"
16
17 "golang.org/x/net/context"
18 )
19
20 // PackageLoader is an implementation of venv.PackageLoader that uses the
21 // CIPD service to fetch packages.
22 //
23 // Packages that use the CIPD loader use the CIPD package name as their Path
24 // and a CIPD version/tag/ref as their Version.
25 type PackageLoader struct {
26 // Options are additional client options to use when generating CIPD cli ents.
27 Options cipd.ClientOptions
28 }
29
30 var _ venv.PackageLoader = (*PackageLoader)(nil)
31
32 // Resolve implements venv.PackageLoader.
33 //
34 // The resulting packages slice will be updated in-place with the resolved
35 // package name and instance ID.
36 func (pl *PackageLoader) Resolve(c context.Context, root string, packages []*vpy thon.Spec_Package) error {
37 if len(packages) == 0 {
38 return nil
39 }
40
41 logging.Debugf(c, "Resolving CIPD packages:")
42 pslice := make(ensure.PackageSlice, len(packages))
43 for i, pkg := range packages {
44 pslice[i] = ensure.PackageDef{
45 PackageTemplate: pkg.Name,
46 UnresolvedVersion: pkg.Version,
47 }
48
49 logging.Debugf(c, "\tUnresolved package: %s", pslice[i])
50 }
51
52 ef := ensure.File{
53 PackagesBySubdir: map[string]ensure.PackageSlice{"": pslice},
54 }
55
56 // Generate a CIPD client. Use the supplied root.
57 opts := pl.Options
58 opts.Root = root
59 client, err := cipd.NewClient(opts)
60 if err != nil {
61 return errors.Annotate(err).Reason("failed to generate CIPD clie nt").Err()
62 }
63
64 // Start a CIPD client batch.
65 client.BeginBatch(c)
66 defer client.EndBatch(c)
67
68 // Resolve our ensure file.
69 resolved, err := ef.Resolve(func(pkg, vers string) (common.Pin, error) {
70 pin, err := client.ResolveVersion(c, pkg, vers)
71 if err != nil {
72 return pin, errors.Annotate(err).Reason("failed to resol ve package %(package)q at version %(version)q").
73 D("package", pkg).
74 D("version", vers).
75 Err()
76 }
77
78 logging.Fields{
79 "package": pkg,
80 "version": vers,
81 }.Debugf(c, "Resolved package to: %s", pin)
82 return pin, nil
83 })
84 if err != nil {
85 return err
86 }
87
88 // Write the results to "packages". All of them should have been install ed
89 // into the root subdir.
90 for i, pkg := range resolved.PackagesBySubdir[""] {
91 packages[i].Name = pkg.PackageName
92 packages[i].Version = pkg.InstanceID
93 }
94 return nil
95 }
96
97 // Ensure implement venv.PackageLoader.
98 //
99 // The packages must be valid (PackageIsComplete). If they aren't, Ensure will
100 // panic.
101 //
102 // The CIPD client that is used for the operation is generated from the supplied
103 // options, opts.
104 func (pl *PackageLoader) Ensure(c context.Context, root string, packages []*vpyt hon.Spec_Package) error {
105 pins, err := packagesToPins(packages)
106 if err != nil {
107 return errors.Annotate(err).Reason("failed to convert packages t o CIPD pins").Err()
108 }
109 pinSlice := common.PinSliceBySubdir{
110 "": pins,
111 }
112
113 // Generate a CIPD client. Use the supplied root.
114 opts := pl.Options
115 opts.Root = root
116 client, err := cipd.NewClient(opts)
117 if err != nil {
118 return errors.Annotate(err).Reason("failed to generate CIPD clie nt").Err()
119 }
120
121 // Start a CIPD client batch.
122 client.BeginBatch(c)
123 defer client.EndBatch(c)
124
125 actionMap, err := client.EnsurePackages(c, pinSlice, false)
126 if err != nil {
127 return errors.Annotate(err).Reason("failed to install CIPD packa ges").Err()
128 }
129 if len(actionMap) > 0 {
130 errorCount := 0
131 for root, action := range actionMap {
132 errorCount += len(action.Errors)
133 for _, err := range action.Errors {
134 logging.Errorf(c, "CIPD root %q action %q for pi n %q encountered error: %s", root, err.Action, err.Pin, err)
135 }
136 }
137 if errorCount > 0 {
138 return errors.Reason("CIPD package installation encounte red %(count)d error(s)").
139 D("count", errorCount).
140 Err()
141 }
142 }
143 return nil
144 }
145
146 func packagesToPins(packages []*vpython.Spec_Package) ([]common.Pin, error) {
147 pins := make([]common.Pin, len(packages))
148 for i, pkg := range packages {
149 pins[i] = common.Pin{
150 PackageName: pkg.Name,
151 InstanceID: pkg.Version,
152 }
153 }
154 return pins, nil
155 }
OLDNEW
« no previous file with comments | « vpython/api/vpython/spec.pb.go ('k') | vpython/spec/load_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698