~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/commands/synctools.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package commands
 
5
 
 
6
import (
 
7
        "bytes"
 
8
        "io"
 
9
 
 
10
        "github.com/juju/cmd"
 
11
        "github.com/juju/loggo"
 
12
        "github.com/juju/version"
 
13
        "launchpad.net/gnuflag"
 
14
 
 
15
        "github.com/juju/juju/apiserver/params"
 
16
        "github.com/juju/juju/cmd/juju/block"
 
17
        "github.com/juju/juju/cmd/modelcmd"
 
18
        "github.com/juju/juju/environs/filestorage"
 
19
        "github.com/juju/juju/environs/sync"
 
20
        envtools "github.com/juju/juju/environs/tools"
 
21
        coretools "github.com/juju/juju/tools"
 
22
)
 
23
 
 
24
var syncTools = sync.SyncTools
 
25
 
 
26
func newSyncToolsCommand() cmd.Command {
 
27
        return modelcmd.Wrap(&syncToolsCommand{})
 
28
}
 
29
 
 
30
// syncToolsCommand copies all the tools from the us-east-1 bucket to the local
 
31
// bucket.
 
32
type syncToolsCommand struct {
 
33
        modelcmd.ModelCommandBase
 
34
        allVersions  bool
 
35
        versionStr   string
 
36
        majorVersion int
 
37
        minorVersion int
 
38
        dryRun       bool
 
39
        dev          bool
 
40
        public       bool
 
41
        source       string
 
42
        stream       string
 
43
        localDir     string
 
44
        destination  string
 
45
}
 
46
 
 
47
var _ cmd.Command = (*syncToolsCommand)(nil)
 
48
 
 
49
const synctoolsDoc = `
 
50
This copies the Juju agent software from the official tools store (located
 
51
at https://streams.canonical.com/juju) into a model. It is generally done
 
52
when the model is without Internet access.
 
53
 
 
54
Instead of the above site, a local directory can be specified as source.
 
55
The online store will, of course, need to be contacted at some point to get
 
56
the software.
 
57
 
 
58
Examples:
 
59
    # Download the software (version auto-selected) to the model:
 
60
    juju sync-tools --debug
 
61
 
 
62
    # Download a specific version of the software locally:
 
63
    juju sync-tools --debug --version 2.0 --local-dir=/home/ubuntu/sync-tools
 
64
 
 
65
    # Get locally available software to the model:
 
66
    juju sync-tools --debug --source=/home/ubuntu/sync-tools
 
67
 
 
68
See Also:
 
69
    juju upgrade-juju
 
70
 
 
71
`
 
72
 
 
73
func (c *syncToolsCommand) Info() *cmd.Info {
 
74
        return &cmd.Info{
 
75
                Name:    "sync-tools",
 
76
                Purpose: "Copy tools from the official tool store into a local model.",
 
77
                Doc:     synctoolsDoc,
 
78
        }
 
79
}
 
80
 
 
81
func (c *syncToolsCommand) SetFlags(f *gnuflag.FlagSet) {
 
82
        f.BoolVar(&c.allVersions, "all", false, "Copy all versions, not just the latest")
 
83
        f.StringVar(&c.versionStr, "version", "", "Copy a specific major[.minor] version")
 
84
        f.BoolVar(&c.dryRun, "dry-run", false, "Don't copy, just print what would be copied")
 
85
        f.BoolVar(&c.dev, "dev", false, "Consider development versions as well as released ones\n    DEPRECATED: use --stream instead")
 
86
        f.BoolVar(&c.public, "public", false, "Tools are for a public cloud, so generate mirrors information")
 
87
        f.StringVar(&c.source, "source", "", "Local source directory")
 
88
        f.StringVar(&c.stream, "stream", "", "Simplestreams stream for which to sync metadata")
 
89
        f.StringVar(&c.localDir, "local-dir", "", "Local destination directory")
 
90
        f.StringVar(&c.destination, "destination", "", "Local destination directory\n    DEPRECATED: use --local-dir instead")
 
91
}
 
92
 
 
93
func (c *syncToolsCommand) Init(args []string) error {
 
94
        if c.destination != "" {
 
95
                // Override localDir with destination as localDir now replaces destination
 
96
                c.localDir = c.destination
 
97
                logger.Infof("Use of the --destination flag is deprecated in 1.18. Please use --local-dir instead.")
 
98
        }
 
99
        if c.versionStr != "" {
 
100
                var err error
 
101
                if c.majorVersion, c.minorVersion, err = version.ParseMajorMinor(c.versionStr); err != nil {
 
102
                        return err
 
103
                }
 
104
        }
 
105
        if c.dev {
 
106
                c.stream = envtools.TestingStream
 
107
        }
 
108
        return cmd.CheckEmpty(args)
 
109
}
 
110
 
 
111
// syncToolsAPI provides an interface with a subset of the
 
112
// api.Client API. This exists to enable mocking.
 
113
type syncToolsAPI interface {
 
114
        FindTools(majorVersion, minorVersion int, series, arch string) (params.FindToolsResult, error)
 
115
        UploadTools(r io.ReadSeeker, v version.Binary, series ...string) (coretools.List, error)
 
116
        Close() error
 
117
}
 
118
 
 
119
var getSyncToolsAPI = func(c *syncToolsCommand) (syncToolsAPI, error) {
 
120
        return c.NewAPIClient()
 
121
}
 
122
 
 
123
func (c *syncToolsCommand) Run(ctx *cmd.Context) (resultErr error) {
 
124
        // Register writer for output on screen.
 
125
        writer := loggo.NewMinimumLevelWriter(
 
126
                cmd.NewCommandLogWriter("juju.environs.sync", ctx.Stdout, ctx.Stderr),
 
127
                loggo.INFO)
 
128
        loggo.RegisterWriter("synctools", writer)
 
129
        defer loggo.RemoveWriter("synctools")
 
130
 
 
131
        sctx := &sync.SyncContext{
 
132
                AllVersions:  c.allVersions,
 
133
                MajorVersion: c.majorVersion,
 
134
                MinorVersion: c.minorVersion,
 
135
                DryRun:       c.dryRun,
 
136
                Stream:       c.stream,
 
137
                Source:       c.source,
 
138
        }
 
139
 
 
140
        if c.localDir != "" {
 
141
                stor, err := filestorage.NewFileStorageWriter(c.localDir)
 
142
                if err != nil {
 
143
                        return err
 
144
                }
 
145
                writeMirrors := envtools.DoNotWriteMirrors
 
146
                if c.public {
 
147
                        writeMirrors = envtools.WriteMirrors
 
148
                }
 
149
                sctx.TargetToolsFinder = sync.StorageToolsFinder{Storage: stor}
 
150
                sctx.TargetToolsUploader = sync.StorageToolsUploader{
 
151
                        Storage:       stor,
 
152
                        WriteMetadata: true,
 
153
                        WriteMirrors:  writeMirrors,
 
154
                }
 
155
        } else {
 
156
                if c.public {
 
157
                        logger.Infof("--public is ignored unless --local-dir is specified")
 
158
                }
 
159
                api, err := getSyncToolsAPI(c)
 
160
                if err != nil {
 
161
                        return err
 
162
                }
 
163
                defer api.Close()
 
164
                adapter := syncToolsAPIAdapter{api}
 
165
                sctx.TargetToolsFinder = adapter
 
166
                sctx.TargetToolsUploader = adapter
 
167
        }
 
168
        return block.ProcessBlockedError(syncTools(sctx), block.BlockChange)
 
169
}
 
170
 
 
171
// syncToolsAPIAdapter implements sync.ToolsFinder and
 
172
// sync.ToolsUploader, adapting a syncToolsAPI. This
 
173
// enables the use of sync.SyncTools with the client
 
174
// API.
 
175
type syncToolsAPIAdapter struct {
 
176
        syncToolsAPI
 
177
}
 
178
 
 
179
func (s syncToolsAPIAdapter) FindTools(majorVersion int, stream string) (coretools.List, error) {
 
180
        result, err := s.syncToolsAPI.FindTools(majorVersion, -1, "", "")
 
181
        if err != nil {
 
182
                return nil, err
 
183
        }
 
184
        if result.Error != nil {
 
185
                if params.IsCodeNotFound(result.Error) {
 
186
                        return nil, coretools.ErrNoMatches
 
187
                }
 
188
                return nil, result.Error
 
189
        }
 
190
        return result.List, nil
 
191
}
 
192
 
 
193
func (s syncToolsAPIAdapter) UploadTools(toolsDir, stream string, tools *coretools.Tools, data []byte) error {
 
194
        _, err := s.syncToolsAPI.UploadTools(bytes.NewReader(data), tools.Version)
 
195
        return err
 
196
}