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

Unified Diff: go/src/infra/tools/cipd/ensure.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/doc.go ('k') | go/src/infra/tools/cipd/ensure_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/ensure.go
diff --git a/go/src/infra/tools/cipd/ensure.go b/go/src/infra/tools/cipd/ensure.go
deleted file mode 100644
index 549bddd050ace9125eb393c2ec4e3927a550b177..0000000000000000000000000000000000000000
--- a/go/src/infra/tools/cipd/ensure.go
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package cipd
-
-import (
- "bufio"
- "fmt"
- "io"
- "net/http"
- "os"
- "path/filepath"
- "strings"
-
- "infra/libs/logging"
-)
-
-// ParseDesiredState parses text file that describes what should be installed
-// by EnsurePackages function. It is a text file where each line has a form:
-// <package name> <desired instance ID>
-// Whitespaces are ignored. Lines that start with '#' are ignored.
-func ParseDesiredState(r io.Reader) ([]PackageState, error) {
- lineNo := 0
- makeError := func(msg string) error {
- return fmt.Errorf("Failed to parse desired state (line %d): %s", lineNo, msg)
- }
-
- out := []PackageState{}
- scanner := bufio.NewScanner(r)
- for scanner.Scan() {
- lineNo++
-
- // Split each line into words, ignore white space.
- tokens := []string{}
- for _, chunk := range strings.Split(scanner.Text(), " ") {
- chunk = strings.TrimSpace(chunk)
- if chunk != "" {
- tokens = append(tokens, chunk)
- }
- }
-
- // Skip empty lines or lines starting with '#'.
- if len(tokens) == 0 || tokens[0][0] == '#' {
- continue
- }
-
- // Each line has a format "<package name> <instance id>".
- if len(tokens) != 2 {
- return nil, makeError("expecting '<package name> <instance id>' line")
- }
- err := ValidatePackageName(tokens[0])
- if err != nil {
- return nil, makeError(err.Error())
- }
- err = ValidateInstanceID(tokens[1])
- if err != nil {
- return nil, makeError(err.Error())
- }
-
- // Good enough.
- out = append(out, PackageState{
- PackageName: tokens[0],
- InstanceID: tokens[1],
- })
- }
-
- return out, nil
-}
-
-// EnsurePackagesOptions contains parameters for EnsurePackages calls.
-type EnsurePackagesOptions struct {
- // ServiceURL is root URL of the backend service, or "" to use default service.
- ServiceURL string
- // ClientFactory knows how to make authenticated http.Client when it is needed. Called lazily.
- ClientFactory func() (*http.Client, error)
- // Log is a logger to use for logs, default is logging.DefaultLogger.
- Log logging.Logger
-
- // Root is a site root directory to modify. Will be created if missing.
- Root string
- // Packages describes the desired state of the site root directory.
- Packages []PackageState
-}
-
-// EnsurePackages is high level interface for installing, removing and updating
-// of packages inside some installation site root. Given a description of
-// what packages (and versions) should be installed it will do all necessary
-// actions to bring the state of the site root to desired one.
-func EnsurePackages(opts EnsurePackagesOptions) error {
- // Make sure a package is specified only once.
- seen := make(map[string]bool, len(opts.Packages))
- for _, p := range opts.Packages {
- if seen[p.PackageName] {
- return fmt.Errorf("Package %s is specified twice", p.PackageName)
- }
- seen[p.PackageName] = true
- }
-
- // Fill in default options.
- if opts.ServiceURL == "" {
- opts.ServiceURL = DefaultServiceURL()
- }
- if opts.Log == nil {
- opts.Log = logging.DefaultLogger
- }
- log := opts.Log
-
- // Ensure site root is a directory (or missing).
- root, err := filepath.Abs(filepath.Clean(opts.Root))
- if err != nil {
- return err
- }
- stat, err := os.Stat(root)
- if err == nil && !stat.IsDir() {
- return fmt.Errorf("Path %s is not a directory", opts.Root)
- }
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- rootExists := (err == nil)
-
- // Enumerate existing packages (only if root already exists).
- existing := []PackageState{}
- if rootExists {
- existing, err = FindDeployed(root)
- if err != nil {
- log.Errorf("Failed to enumerate installed packages: %s", err)
- return err
- }
- }
-
- // Figure out what needs to be updated and deleted, log it.
- toDeploy, toDelete := buildActionPlan(opts.Packages, existing)
- if len(toDeploy) == 0 && len(toDelete) == 0 {
- log.Infof("Everything is up-to-date.")
- return nil
- }
- if len(toDeploy) != 0 {
- log.Infof("Packages to be installed:")
- for _, state := range toDeploy {
- log.Infof(" %s:%s", state.PackageName, state.InstanceID)
- }
- }
- if len(toDelete) != 0 {
- log.Infof("Packages to be removed:")
- for _, state := range toDelete {
- log.Infof(" %s", state.PackageName)
- }
- }
-
- // Create the site root directory before installing anything there.
- if len(toDeploy) != 0 && !rootExists {
- err = os.MkdirAll(root, 0777)
- if err != nil {
- return err
- }
- }
-
- // Updating packages requires interaction with the server, create the client.
- client := http.DefaultClient
- if len(toDeploy) != 0 && opts.ClientFactory != nil {
- client, err = opts.ClientFactory()
- if err != nil {
- return err
- }
- }
-
- // Remove all unneeded stuff.
- errors := []error{}
- for _, state := range toDelete {
- err = RemoveDeployed(root, state.PackageName)
- if err != nil {
- log.Errorf("Failed to remove %s - %s", state.PackageName, err)
- errors = append(errors, err)
- }
- }
-
- // Install all new stuff.
- for _, state := range toDeploy {
- err = FetchAndDeployInstance(root, FetchInstanceOptions{
- ServiceURL: opts.ServiceURL,
- Client: client,
- Log: opts.Log,
- PackageName: state.PackageName,
- InstanceID: state.InstanceID,
- })
- if err != nil {
- log.Errorf("Failed to install %s:%s - %s", state.PackageName, state.InstanceID, err)
- errors = append(errors, err)
- }
- }
-
- if len(errors) == 0 {
- log.Infof("All changes applied.")
- return nil
- }
- return fmt.Errorf("Some actions failed: %v", errors)
-}
-
-func buildActionPlan(desired []PackageState, existing []PackageState) (toDeploy []PackageState, toDelete []PackageState) {
- // Figure out what needs to be installed or updated.
- for _, d := range desired {
- alreadyGood := false
- for _, e := range existing {
- if e.PackageName == d.PackageName {
- alreadyGood = e.InstanceID == d.InstanceID
- break
- }
- }
- if !alreadyGood {
- toDeploy = append(toDeploy, d)
- }
- }
-
- // Figure out what needs to be removed.
- for _, e := range existing {
- keep := false
- for _, d := range desired {
- if e.PackageName == d.PackageName {
- keep = true
- break
- }
- }
- if !keep {
- toDelete = append(toDelete, e)
- }
- }
-
- return
-}
« no previous file with comments | « go/src/infra/tools/cipd/doc.go ('k') | go/src/infra/tools/cipd/ensure_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698