| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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 main | |
| 6 | |
| 7 import ( | |
| 8 "os/user" | |
| 9 "strings" | |
| 10 | |
| 11 "github.com/luci/luci-go/common/errors" | |
| 12 "github.com/luci/luci-go/deploytool/api/deploy" | |
| 13 ) | |
| 14 | |
| 15 type cloudProjectVersion struct { | |
| 16 // minorSourceVersion is the minorVersion parameter of the component's | |
| 17 // origin Source. | |
| 18 minorSourceVersion string | |
| 19 // majorSourceVersion is the majorVersion parameter of the component's | |
| 20 // origin Source. | |
| 21 majorSourceVersion string | |
| 22 | |
| 23 // taintedUser, if not empty, indicates that this version is tainted and
names | |
| 24 // the user on whose behalf it was deployed. | |
| 25 taintedUser string | |
| 26 } | |
| 27 | |
| 28 func makeCloudProjectVersion(cp *layoutDeploymentCloudProject, src *layoutSource
) (*cloudProjectVersion, error) { | |
| 29 return (cloudProjectVersionBuilder{}).build(cp, src) | |
| 30 } | |
| 31 | |
| 32 type cloudProjectVersionBuilder struct { | |
| 33 currentUser func() (string, error) | |
| 34 } | |
| 35 | |
| 36 func (b cloudProjectVersionBuilder) build(cp *layoutDeploymentCloudProject, src
*layoutSource) (*cloudProjectVersion, error) { | |
| 37 switch vs := cp.VersionScheme; vs { | |
| 38 case deploy.Deployment_CloudProject_DEFAULT: | |
| 39 cpv := cloudProjectVersion{ | |
| 40 minorSourceVersion: cloudVersionStringNormalize(src.Mino
rVersion), | |
| 41 majorSourceVersion: cloudVersionStringNormalize(src.Majo
rVersion), | |
| 42 } | |
| 43 | |
| 44 if src.sg.Tainted { | |
| 45 username, err := b.getCurrentUser() | |
| 46 if err != nil { | |
| 47 return nil, errors.Annotate(err).Reason("could n
ot get tained user").Err() | |
| 48 } | |
| 49 cpv.taintedUser = cloudVersionStringNormalize(username) | |
| 50 } | |
| 51 return &cpv, nil | |
| 52 | |
| 53 default: | |
| 54 return nil, errors.Reason("unknown version scheme %(scheme)v").D
("scheme", vs).Err() | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 func (b *cloudProjectVersionBuilder) getCurrentUser() (string, error) { | |
| 59 if b.currentUser != nil { | |
| 60 return b.currentUser() | |
| 61 } | |
| 62 | |
| 63 // Default "currentUser" function uses "os.User". | |
| 64 user, err := user.Current() | |
| 65 if err != nil { | |
| 66 return "", errors.Annotate(err).Reason("could not get tained use
r").Err() | |
| 67 } | |
| 68 return user.Username, nil | |
| 69 } | |
| 70 | |
| 71 func parseCloudProjectVersion(vs deploy.Deployment_CloudProject_VersionScheme, v
string) ( | |
| 72 *cloudProjectVersion, error) { | |
| 73 var cpv cloudProjectVersion | |
| 74 switch vs { | |
| 75 case deploy.Deployment_CloudProject_DEFAULT: | |
| 76 parts := strings.Split(v, "-") | |
| 77 | |
| 78 switch len(parts) { | |
| 79 case 4: | |
| 80 // <min>-<maj>-tainted-<user> | |
| 81 cpv.taintedUser = parts[3] | |
| 82 fallthrough | |
| 83 | |
| 84 case 2: | |
| 85 // <min>-<maj> | |
| 86 cpv.minorSourceVersion = parts[0] | |
| 87 cpv.majorSourceVersion = parts[1] | |
| 88 return &cpv, nil | |
| 89 | |
| 90 default: | |
| 91 return nil, errors.Reason("bad version %(version)q for s
cheme %(scheme)T"). | |
| 92 D("version", v).D("scheme", vs).Err() | |
| 93 } | |
| 94 | |
| 95 default: | |
| 96 return nil, errors.Reason("unknown version scheme %(scheme)T").D
("scheme", vs).Err() | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 func (v *cloudProjectVersion) String() string { | |
| 101 var partsArray [5]string | |
| 102 parts := partsArray[:0] | |
| 103 | |
| 104 parts = append(parts, []string{v.minorSourceVersion, v.majorSourceVersio
n}...) | |
| 105 if tu := v.taintedUser; tu != "" { | |
| 106 parts = append(parts, []string{"tainted", tu}...) | |
| 107 } | |
| 108 return strings.Join(parts, "-") | |
| 109 } | |
| 110 | |
| 111 func (v *cloudProjectVersion) isTainted() bool { return v
.taintedUser != "" } | |
| 112 func (v *cloudProjectVersion) Equals(other *cloudProjectVersion) bool { return *
v == *other } | |
| 113 | |
| 114 // cloudVersionStringNormalize converts an input string into a cloud version- | |
| 115 // normalized string. | |
| 116 // | |
| 117 // Any character other than [A-Za-z0-9_] is converted to an underscore. | |
| 118 func cloudVersionStringNormalize(v string) string { | |
| 119 return strings.Map(func(r rune) rune { | |
| 120 if (r >= 'a' && r <= 'z') || | |
| 121 (r >= 'A' && r <= 'Z') || | |
| 122 (r >= '0' && r <= '9') { | |
| 123 return r | |
| 124 } | |
| 125 return '_' | |
| 126 }, v) | |
| 127 } | |
| OLD | NEW |