Index: environs/sync/sync.go |
=== modified file 'environs/sync/sync.go' |
--- environs/sync/sync.go 2013-09-13 04:16:42 +0000 |
+++ environs/sync/sync.go 2013-09-16 10:47:28 +0000 |
@@ -8,14 +8,17 @@ |
"crypto/sha256" |
"fmt" |
"io" |
+ "io/ioutil" |
"net/http" |
+ "os" |
+ "path/filepath" |
"launchpad.net/loggo" |
"launchpad.net/juju-core/environs" |
"launchpad.net/juju-core/environs/filestorage" |
envtools "launchpad.net/juju-core/environs/tools" |
- "launchpad.net/juju-core/provider/ec2" |
+ "launchpad.net/juju-core/provider/ec2/httpstorage" |
coretools "launchpad.net/juju-core/tools" |
"launchpad.net/juju-core/version" |
) |
@@ -89,7 +92,7 @@ |
logger.Infof("found %d recent tools (version %s)", len(sourceTools), latest) |
} |
for _, tool := range sourceTools { |
- logger.Debugf("found source tool: %s", tool) |
+ logger.Debugf("found source tool: %v", tool) |
} |
logger.Infof("listing target bucket") |
@@ -101,7 +104,7 @@ |
return err |
} |
for _, tool := range targetTools { |
- logger.Debugf("found target tool: %s", tool) |
+ logger.Debugf("found target tool: %v", tool) |
} |
missing := sourceTools.Exclude(targetTools) |
@@ -127,7 +130,7 @@ |
// selectSourceStorage returns a storage reader based on the source setting. |
func selectSourceStorage(syncContext *SyncContext) (environs.StorageReader, error) { |
if syncContext.Source == "" { |
- return ec2.NewHTTPStorageReader(DefaultToolsLocation), nil |
+ return httpstorage.NewHTTPStorageReader(DefaultToolsLocation), nil |
} |
return filestorage.NewFileStorageReader(syncContext.Source) |
} |
@@ -175,3 +178,108 @@ |
tool.Size = nBytes |
return dest.Put(toolsName, buf, nBytes) |
} |
+ |
+// copyFile writes the contents of the given source file to dest. |
+func copyFile(dest, source string) error { |
+ df, err := os.Create(dest) |
+ if err != nil { |
+ return err |
+ } |
+ f, err := os.Open(source) |
+ if err != nil { |
+ return err |
+ } |
+ defer f.Close() |
+ _, err = io.Copy(df, f) |
+ return err |
+} |
+ |
+// Upload builds whatever version of launchpad.net/juju-core is in $GOPATH, |
+// uploads it to the given storage, and returns a Tools instance describing |
+// them. If forceVersion is not nil, the uploaded tools bundle will report |
+// the given version number; if any fakeSeries are supplied, additional copies |
+// of the built tools will be uploaded for use by machines of those series. |
+// Juju tools built for one series do not necessarily run on another, but this |
+// func exists only for development use cases. |
+func Upload(storage environs.Storage, forceVersion *version.Number, fakeSeries ...string) (*coretools.Tools, error) { |
+ // TODO(rog) find binaries from $PATH when not using a development |
+ // version of juju within a $GOPATH. |
+ |
+ logger.Debugf("Uploading tools for %v", fakeSeries) |
+ // We create the entire archive before asking the environment to |
+ // start uploading so that we can be sure we have archived |
+ // correctly. |
+ f, err := ioutil.TempFile("", "juju-tgz") |
+ if err != nil { |
+ return nil, err |
+ } |
+ defer f.Close() |
+ defer os.Remove(f.Name()) |
+ toolsVersion, sha256Hash, err := envtools.BundleTools(f, forceVersion) |
+ if err != nil { |
+ return nil, err |
+ } |
+ fileInfo, err := f.Stat() |
+ if err != nil { |
+ return nil, fmt.Errorf("cannot stat newly made tools archive: %v", err) |
+ } |
+ size := fileInfo.Size() |
+ logger.Infof("built %v (%dkB)", toolsVersion, (size+512)/1024) |
+ baseToolsDir, err := ioutil.TempDir("", "") |
+ if err != nil { |
+ return nil, err |
+ } |
+ defer os.RemoveAll(baseToolsDir) |
+ putTools := func(vers version.Binary) (string, error) { |
+ envtools.SetToolPrefix(envtools.NewToolPrefix) |
+ defer func() { |
+ envtools.SetToolPrefix(envtools.DefaultToolPrefix) |
axw1
2013/09/17 04:23:11
Is it conceivable that someone calls Upload with N
wallyworld
2013/09/17 05:30:16
I can't happen like that in practice. But I've mad
|
+ }() |
+ name := envtools.StorageName(vers) |
+ err = copyFile(filepath.Join(baseToolsDir, name), f.Name()) |
+ if err != nil { |
+ return "", err |
+ } |
+ return name, nil |
+ } |
+ toolsDir := filepath.Join(baseToolsDir, "tools/releases") |
+ err = os.MkdirAll(toolsDir, 0755) |
+ if err != nil { |
+ return nil, err |
+ } |
+ for _, series := range fakeSeries { |
+ if series != toolsVersion.Series { |
+ fakeVersion := toolsVersion |
+ fakeVersion.Series = series |
+ if _, err := putTools(fakeVersion); err != nil { |
+ return nil, err |
+ } |
+ } |
+ } |
+ name, err := putTools(toolsVersion) |
+ if err != nil { |
+ return nil, err |
+ } |
+ syncContext := &SyncContext{ |
+ Source: baseToolsDir, |
+ Target: storage, |
+ AllVersions: true, |
+ Dev: true, |
+ MajorVersion: toolsVersion.Major, |
+ MinorVersion: -1, |
+ } |
+ err = SyncTools(syncContext) |
+ if err != nil { |
+ return nil, err |
+ } |
+ url, err := storage.URL(name) |
+ if err != nil { |
+ return nil, err |
+ } |
+ return &coretools.Tools{ |
+ Version: toolsVersion, |
+ URL: url, |
+ Size: size, |
+ SHA256: sha256Hash, |
+ }, nil |
+} |