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

Unified Diff: go/src/infra/tools/cipd/local/deployer.go

Issue 1129043003: cipd: Refactor client to make it more readable. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « go/src/infra/tools/cipd/local/builder_test.go ('k') | go/src/infra/tools/cipd/local/deployer_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: go/src/infra/tools/cipd/local/deployer.go
diff --git a/go/src/infra/tools/cipd/deployer.go b/go/src/infra/tools/cipd/local/deployer.go
similarity index 76%
rename from go/src/infra/tools/cipd/deployer.go
rename to go/src/infra/tools/cipd/local/deployer.go
index 68bace5278635e72b9970c813a849ddf1737f2ad..9c490b93e97bb5bf37eb0157c482276c1572445e 100644
--- a/go/src/infra/tools/cipd/deployer.go
+++ b/go/src/infra/tools/cipd/local/deployer.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package cipd
+package local
import (
"crypto/sha1"
@@ -15,9 +15,12 @@ import (
"strings"
"sync"
"time"
+
+ "infra/libs/logging"
+ "infra/tools/cipd/common"
)
-// TODO(vadimsh): Make it work on Windows, verify it works on Mac.
+// TODO(vadimsh): Make it work on Windows.
// TODO(vadimsh): How to handle path conflicts between two packages? Currently
// the last one installed wins.
@@ -42,74 +45,67 @@ import (
// Some efforts are made to make sure that during the deployment a window of
// inconsistency in the file system is as small as possible.
-// Subdirectory of site root to extract packages to.
-const packagesDir = siteServiceDir + "/pkgs"
+// packagesDir is a subdirectory of site root to extract packages to.
+const packagesDir = SiteServiceDir + "/pkgs"
-// Name of a symlink that points to latest deployed version.
+// currentSymlink is a name of a symlink that points to latest deployed version.
const currentSymlink = "_current"
-// PackageState contains information about single deployed package.
-type PackageState struct {
- // PackageName identifies the package.
- PackageName string
- // InstanceID is ID of the installed package instance (SHA1 of package contents).
- InstanceID string
-}
+// log is logger to use for logs produced by this file.
+// TODO(vadimsh): Propagate as parameter.
+var log = logging.DefaultLogger
-// DeployInstance installs a specific instance of a package (identified by
-// InstanceID()) into a site root directory. It unpacks the package into
-// <root>/.cipd/pkgs/*, and rearranges symlinks to point to unpacked files.
-// It tries to make it as "atomic" as possibly.
-func DeployInstance(root string, inst PackageInstance) (state PackageState, err error) {
- root, err = filepath.Abs(filepath.Clean(root))
+// DeployInstance installs a specific instance of a package into a site root
+// directory. It unpacks the package into <root>/.cipd/pkgs/*, and rearranges
+// symlinks to point to unpacked files. It tries to make it as "atomic" as
+// possible. Returns information about the deployed instance.
+func DeployInstance(root string, inst PackageInstance) (common.Pin, error) {
+ root, err := filepath.Abs(filepath.Clean(root))
if err != nil {
- return
+ return common.Pin{}, err
}
- log.Infof("Deploying %s:%s into %s", inst.PackageName(), inst.InstanceID(), root)
+ pin := inst.Pin()
+ log.Infof("Deploying %s into %s", pin, root)
// Be paranoid.
- err = ValidatePackageName(inst.PackageName())
+ err = common.ValidatePin(pin)
if err != nil {
- return
- }
- err = ValidateInstanceID(inst.InstanceID())
- if err != nil {
- return
+ return common.Pin{}, err
}
// Remember currently deployed version (to remove it later). Do not freak out
// if it's not there (prevID is "" in that case).
oldFiles := makeStringSet()
- prevID := findDeployedInstance(root, inst.PackageName(), oldFiles)
+ prevID := findDeployedInstance(root, pin.PackageName, oldFiles)
// Extract new version to a final destination.
newFiles := makeStringSet()
destPath, err := deployInstance(root, inst, newFiles)
if err != nil {
- return
+ return common.Pin{}, err
}
// Switch '_current' symlink to point to a new package instance. It is a
// point of no return. The function must not fail going forward.
- mainSymlinkPath := packagePath(root, inst.PackageName(), currentSymlink)
- err = ensureSymlink(mainSymlinkPath, inst.InstanceID())
+ mainSymlinkPath := packagePath(root, pin.PackageName, currentSymlink)
+ err = ensureSymlink(mainSymlinkPath, pin.InstanceID)
if err != nil {
ensureDirectoryGone(destPath)
- return
+ return common.Pin{}, err
}
// Asynchronously remove previous version (best effort).
wg := sync.WaitGroup{}
defer wg.Wait()
- if prevID != "" && prevID != inst.InstanceID() {
+ if prevID != "" && prevID != pin.InstanceID {
wg.Add(1)
go func() {
defer wg.Done()
- ensureDirectoryGone(packagePath(root, inst.PackageName(), prevID))
+ ensureDirectoryGone(packagePath(root, pin.PackageName, prevID))
}()
}
- log.Infof("Adjusting symlinks for %s", inst.PackageName())
+ log.Infof("Adjusting symlinks for %s", pin.PackageName)
// Make symlinks in the site directory for all new files. Reference a package
// root via '_current' symlink (instead of direct destPath), to make
@@ -123,33 +119,30 @@ func DeployInstance(root string, inst PackageInstance) (state PackageState, err
}
// Verify it's all right, read the manifest.
- state, err = CheckDeployed(root, inst.PackageName())
- if err == nil && state.InstanceID != inst.InstanceID() {
- err = fmt.Errorf("Other package instance (%s) was deployed concurrently", state.InstanceID)
+ newPin, err := CheckDeployed(root, pin.PackageName)
+ if err == nil && newPin.InstanceID != pin.InstanceID {
+ err = fmt.Errorf("Other instance (%s) was deployed concurrently", newPin.InstanceID)
}
if err == nil {
- log.Infof("Successfully deployed %s:%s", inst.PackageName(), inst.InstanceID())
+ log.Infof("Successfully deployed %s", pin)
} else {
- log.Errorf("Failed to deploy %s:%s: %s", inst.PackageName(), inst.InstanceID(), err.Error())
+ log.Errorf("Failed to deploy %s: %s", pin, err)
}
- return
+ return newPin, err
}
// CheckDeployed checks whether a given package is deployed and returns
// information about it if it is.
-func CheckDeployed(root string, pkg string) (state PackageState, err error) {
- state, err = readPackageState(packagePath(root, pkg))
- if err != nil {
- return
- }
- if state.PackageName != pkg {
+func CheckDeployed(root string, pkg string) (common.Pin, error) {
+ pin, err := readPackageState(packagePath(root, pkg))
+ if err == nil && pin.PackageName != pkg {
err = fmt.Errorf("Package path and package name in the manifest do not match")
}
- return
+ return pin, err
}
// FindDeployed returns a list of packages deployed to a site root.
-func FindDeployed(root string) (out []PackageState, err error) {
+func FindDeployed(root string) (out []common.Pin, err error) {
root, err = filepath.Abs(filepath.Clean(root))
if err != nil {
return
@@ -167,18 +160,18 @@ func FindDeployed(root string) (out []PackageState, err error) {
}
// Read the package name from the package manifest. Skip broken stuff.
- found := map[string]PackageState{}
+ found := map[string]common.Pin{}
keys := []string{}
for _, info := range infos {
// Attempt to read the manifest. If it is there -> valid package is found.
if info.IsDir() {
- state, err := readPackageState(filepath.Join(pkgs, info.Name()))
+ pin, err := readPackageState(filepath.Join(pkgs, info.Name()))
if err == nil {
// Ignore duplicate entries, they can appear if someone messes with
// pkgs/* structure manually.
- if _, ok := found[state.PackageName]; !ok {
- keys = append(keys, state.PackageName)
- found[state.PackageName] = state
+ if _, ok := found[pin.PackageName]; !ok {
+ keys = append(keys, pin.PackageName)
+ found[pin.PackageName] = pin
}
}
}
@@ -186,7 +179,7 @@ func FindDeployed(root string) (out []PackageState, err error) {
// Sort by package name.
sort.Strings(keys)
- out = make([]PackageState, len(found))
+ out = make([]common.Pin, len(found))
for i, k := range keys {
out[i] = found[k]
}
@@ -202,7 +195,7 @@ func RemoveDeployed(root string, packageName string) error {
log.Infof("Removing %s from %s", packageName, root)
// Be paranoid.
- err = ValidatePackageName(packageName)
+ err = common.ValidatePackageName(packageName)
if err != nil {
return err
}
@@ -244,13 +237,13 @@ func deployInstance(root string, inst PackageInstance, files stringSet) (string,
// Extract new version to a final destination. ExtractPackageInstance knows
// how to build full paths and how to atomically extract a package. No need
// to delete garbage if it fails.
- destPath := packagePath(root, inst.PackageName(), inst.InstanceID())
+ destPath := packagePath(root, inst.Pin().PackageName, inst.Pin().InstanceID)
err := ExtractInstance(inst, NewFileSystemDestination(destPath))
if err != nil {
return "", err
}
// Enumerate files inside. Nuke it and fail if it's unreadable.
- err = scanPackageDir(packagePath(root, inst.PackageName(), inst.InstanceID()), files)
+ err = scanPackageDir(packagePath(root, inst.Pin().PackageName, inst.Pin().InstanceID), files)
if err != nil {
ensureDirectoryGone(destPath)
return "", err
@@ -270,12 +263,12 @@ func linkFilesToRoot(root string, packageRoot string, files stringSet) {
// E.g. ../.cipd/pkgs/name/_current/bin/tool.
targetRel, err := filepath.Rel(filepath.Dir(symlinkAbs), targetAbs)
if err != nil {
- log.Warnf("Can't get relative path from %s to %s", filepath.Dir(symlinkAbs), targetAbs)
+ log.Warningf("Can't get relative path from %s to %s", filepath.Dir(symlinkAbs), targetAbs)
continue
}
err = ensureSymlink(symlinkAbs, targetRel)
if err != nil {
- log.Warnf("Failed to create symlink for %s", relPath)
+ log.Warningf("Failed to create symlink for %s", relPath)
continue
}
}
@@ -307,7 +300,7 @@ func packagePath(root string, pkg string, rest ...string) string {
// components of the package name + stripped SHA1 of the whole package name.
func packageNameDigest(pkg string) string {
// Be paranoid.
- err := ValidatePackageName(pkg)
+ err := common.ValidatePackageName(pkg)
if err != nil {
panic(err.Error())
}
@@ -329,34 +322,32 @@ func packageNameDigest(pkg string) string {
}
// readPackageState reads package manifest of a deployed package instance and
-// returns corresponding PackageState object.
-func readPackageState(packageDir string) (state PackageState, err error) {
+// returns corresponding Pin object.
+func readPackageState(packageDir string) (common.Pin, error) {
// Resolve _current symlink to a concrete instance ID.
current, err := os.Readlink(filepath.Join(packageDir, currentSymlink))
if err != nil {
- return
+ return common.Pin{}, err
}
- err = ValidateInstanceID(current)
+ err = common.ValidateInstanceID(current)
if err != nil {
- err = fmt.Errorf("Symlink target doesn't look like a valid instance id")
- return
+ return common.Pin{}, fmt.Errorf("Symlink target doesn't look like a valid instance id")
}
// Read the manifest from the instance directory.
manifestPath := filepath.Join(packageDir, current, filepath.FromSlash(manifestName))
r, err := os.Open(manifestPath)
if err != nil {
- return
+ return common.Pin{}, err
}
defer r.Close()
manifest, err := readManifest(r)
if err != nil {
- return
+ return common.Pin{}, err
}
- state = PackageState{
+ return common.Pin{
PackageName: manifest.PackageName,
InstanceID: current,
- }
- return
+ }, nil
}
// ensureSymlink atomically creates a symlink pointing to a target. It will
@@ -405,7 +396,7 @@ func scanPackageDir(root string, out stringSet) error {
if err != nil {
return err
}
- if rel == packageServiceDir || rel == siteServiceDir {
+ if rel == packageServiceDir || rel == SiteServiceDir {
return filepath.SkipDir
}
if info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 {
@@ -422,14 +413,14 @@ func ensureDirectoryGone(path string) error {
err := os.Rename(path, temp)
if err != nil {
if !os.IsNotExist(err) {
- log.Warnf("Failed to rename directory %s: %v", path, err)
+ log.Warningf("Failed to rename directory %s: %v", path, err)
return err
}
return nil
}
err = os.RemoveAll(temp)
if err != nil {
- log.Warnf("Failed to remove directory %s: %v", temp, err)
+ log.Warningf("Failed to remove directory %s: %v", temp, err)
return err
}
return nil
@@ -439,7 +430,7 @@ func ensureDirectoryGone(path string) error {
func ensureFileGone(path string) error {
err := os.Remove(path)
if err != nil && !os.IsNotExist(err) {
- log.Warnf("Failed to remove %s", path)
+ log.Warningf("Failed to remove %s", path)
return err
}
return nil
« no previous file with comments | « go/src/infra/tools/cipd/local/builder_test.go ('k') | go/src/infra/tools/cipd/local/deployer_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698