~rogpeppe/juju-core/438-local-instance-Addresses

« back to all changes in this revision

Viewing changes to cmd/plugins/juju-metadata/toolsmetadata.go

  • Committer: John Arbash Meinel
  • Date: 2013-09-15 07:36:52 UTC
  • mfrom: (1817 juju-core)
  • mto: This revision was merged to the branch mainline in revision 1882.
  • Revision ID: john@arbash-meinel.com-20130915073652-80jnupeguvr1klea
Merge trunk, resolve conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
package main
5
5
 
6
6
import (
7
 
        "crypto/sha256"
8
7
        "fmt"
9
 
        "hash"
10
 
        "io"
11
 
        "io/ioutil"
12
 
        "net/http"
13
 
        "os"
14
 
        "path/filepath"
15
 
        "time"
16
8
 
17
9
        "launchpad.net/gnuflag"
 
10
        "launchpad.net/loggo"
18
11
 
19
12
        "launchpad.net/juju-core/cmd"
20
 
        "launchpad.net/juju-core/environs"
21
13
        "launchpad.net/juju-core/environs/config"
22
 
        "launchpad.net/juju-core/environs/localstorage"
23
 
        "launchpad.net/juju-core/environs/simplestreams"
 
14
        "launchpad.net/juju-core/environs/filestorage"
24
15
        "launchpad.net/juju-core/environs/sync"
25
16
        "launchpad.net/juju-core/environs/tools"
26
17
        "launchpad.net/juju-core/provider/ec2"
56
47
}
57
48
 
58
49
func (c *ToolsMetadataCommand) Run(context *cmd.Context) error {
 
50
        loggo.RegisterWriter("toolsmetadata", cmd.NewCommandLogWriter("juju.environs.tools", context.Stdout, context.Stderr), loggo.INFO)
 
51
        defer loggo.RemoveWriter("toolsmetadata")
59
52
        if c.metadataDir == "" {
60
53
                c.metadataDir = config.JujuHome()
61
54
        }
62
55
        c.metadataDir = utils.NormalizePath(c.metadataDir)
63
56
 
64
 
        // Create a StorageReader that will get a tools list from the local disk.
65
 
        // Since ReadList expects tools to be immediately under "tools/", and we
66
 
        // want them to be in tools/releases, we have to wrap the storage.
67
 
        listener, err := localstorage.Serve("127.0.0.1:0", c.metadataDir)
 
57
        sourceStorage, err := filestorage.NewFileStorageReader(c.metadataDir)
68
58
        if err != nil {
69
59
                return err
70
60
        }
71
 
        defer listener.Close()
72
 
        var sourceStorage environs.StorageReader = localstorage.Client(listener.Addr().String())
73
 
        sourceStorage = prefixedToolsStorage{sourceStorage}
74
 
 
75
61
        fmt.Fprintln(context.Stdout, "Finding tools...")
76
62
        const minorVersion = -1
77
63
        toolsList, err := tools.ReadList(sourceStorage, version.Current.Major, minorVersion)
83
69
                return err
84
70
        }
85
71
 
86
 
        metadata := make([]*tools.ToolsMetadata, len(toolsList))
87
 
        for i, t := range toolsList {
88
 
                var size int64
89
 
                var sha256hex string
90
 
                if c.fetch {
91
 
                        fmt.Fprintln(context.Stdout, "Fetching tools to generate hash:", t.URL)
92
 
                        var sha256hash hash.Hash
93
 
                        size, sha256hash, err = fetchToolsHash(t.URL)
94
 
                        if err != nil {
95
 
                                return err
96
 
                        }
97
 
                        sha256hex = fmt.Sprintf("%x", sha256hash.Sum(nil))
98
 
                }
99
 
 
100
 
                path := fmt.Sprintf("releases/juju-%s-%s-%s.tgz", t.Version.Number, t.Version.Series, t.Version.Arch)
101
 
                metadata[i] = &tools.ToolsMetadata{
102
 
                        Release:  t.Version.Series,
103
 
                        Version:  t.Version.Number.String(),
104
 
                        Arch:     t.Version.Arch,
105
 
                        Path:     path,
106
 
                        FileType: "tar.gz",
107
 
                        Size:     size,
108
 
                        SHA256:   sha256hex,
109
 
                }
110
 
        }
111
 
 
112
 
        index, products, err := tools.MarshalToolsMetadataJSON(metadata, time.Now())
113
 
        if err != nil {
114
 
                return err
115
 
        }
116
 
        objects := []struct {
117
 
                path string
118
 
                data []byte
119
 
        }{
120
 
                {simplestreams.DefaultIndexPath + simplestreams.UnsignedSuffix, index},
121
 
                {tools.ProductMetadataPath, products},
122
 
        }
123
 
        for _, object := range objects {
124
 
                path := filepath.Join(c.metadataDir, "tools", object.path)
125
 
                fmt.Fprintf(context.Stdout, "Writing %s\n", path)
126
 
                if err = writeFile(path, object.data); err != nil {
127
 
                        return err
128
 
                }
129
 
        }
130
 
        return nil
131
 
}
132
 
 
133
 
func writeFile(path string, data []byte) error {
134
 
        dir := filepath.Dir(path)
135
 
        if err := os.MkdirAll(dir, 0755); err != nil && !os.IsExist(err) {
136
 
                return err
137
 
        }
138
 
        return ioutil.WriteFile(path, data, 0644)
139
 
}
140
 
 
141
 
// fetchToolsHash fetches the file at the specified URL,
142
 
// and calculates its size in bytes and computes a SHA256
143
 
// hash of its contents.
144
 
func fetchToolsHash(url string) (size int64, sha256hash hash.Hash, err error) {
145
 
        resp, err := http.Get(url)
146
 
        if err != nil {
147
 
                return 0, nil, err
148
 
        }
149
 
        sha256hash = sha256.New()
150
 
        size, err = io.Copy(sha256hash, resp.Body)
151
 
        resp.Body.Close()
152
 
        return size, sha256hash, err
153
 
}
154
 
 
155
 
const fromprefix = "tools/"
156
 
const toprefix = "tools/releases/"
157
 
 
158
 
type prefixedToolsStorage struct {
159
 
        environs.StorageReader
160
 
}
161
 
 
162
 
func (s prefixedToolsStorage) translate(name string) string {
163
 
        return toprefix + name[len(fromprefix):]
164
 
}
165
 
 
166
 
func (s prefixedToolsStorage) Get(name string) (io.ReadCloser, error) {
167
 
        return s.StorageReader.Get(s.translate(name))
168
 
}
169
 
 
170
 
func (s prefixedToolsStorage) List(prefix string) ([]string, error) {
171
 
        names, err := s.StorageReader.List(s.translate(prefix))
172
 
        if err == nil {
173
 
                for i, name := range names {
174
 
                        names[i] = fromprefix + name[len(toprefix):]
175
 
                }
176
 
        }
177
 
        return names, err
178
 
}
179
 
 
180
 
func (s prefixedToolsStorage) URL(name string) (string, error) {
181
 
        return s.StorageReader.URL(s.translate(name))
 
72
        targetStorage, err := filestorage.NewFileStorageWriter(c.metadataDir)
 
73
        if err != nil {
 
74
                return err
 
75
        }
 
76
        return tools.WriteMetadata(toolsList, c.fetch, targetStorage)
182
77
}