Left: | ||
Right: |
OLD | NEW |
---|---|
1 package main | 1 package main |
2 | 2 |
3 import ( | 3 import ( |
4 "errors" | 4 "errors" |
5 "fmt" | 5 "fmt" |
6 "launchpad.net/gnuflag" | 6 "launchpad.net/gnuflag" |
7 "launchpad.net/juju-core/charm" | 7 "launchpad.net/juju-core/charm" |
8 "launchpad.net/juju-core/cmd" | 8 "launchpad.net/juju-core/cmd" |
9 "launchpad.net/juju-core/juju" | 9 "launchpad.net/juju-core/juju" |
10 "launchpad.net/juju-core/state" | 10 "launchpad.net/juju-core/state" |
11 "os" | 11 "os" |
12 ) | 12 ) |
13 | 13 |
14 // UpgradeCharm is responsible for upgrading a service's charm. | 14 // UpgradeCharm is responsible for upgrading a service's charm. |
15 type UpgradeCharmCommand struct { | 15 type UpgradeCharmCommand struct { |
16 EnvCommandBase | 16 EnvCommandBase |
17 ServiceName string | 17 ServiceName string |
18 Force bool | 18 Force bool |
19 RepoPath string // defaults to JUJU_REPOSITORY | 19 RepoPath string // defaults to JUJU_REPOSITORY |
20 SwitchURL string | |
21 Revision int // defaults to -1 (latest) | |
20 } | 22 } |
21 | 23 |
22 const upgradeCharmDoc = ` | 24 const upgradeCharmDoc = ` |
23 When no flags are set, the service's charm will be upgraded to the latest | 25 When no flags are set, the service's charm will be upgraded to the latest |
24 revision available in the repository from which it was originally deployed. | 26 revision available in the repository from which it was originally deployed. |
25 | 27 |
26 If the charm came from a local repository, its path will be assumed to be | 28 If the charm came from a local repository, its path will be assumed to be |
27 $JUJU_REPOSITORY unless overridden by --repository. If there is no newer | 29 $JUJU_REPOSITORY unless overridden by --repository. If there is no newer |
28 revision of a local charm directory, the local directory's revision will be | 30 revision of a local charm directory, the local directory's revision will be |
29 automatically incremented to create a newer charm. | 31 automatically incremented to create a newer charm. |
30 | 32 |
31 The local repository behaviour is tuned specifically to the workflow of a charm | 33 The local repository behaviour is tuned specifically to the workflow of a charm |
32 author working on a single client machine; use of local repositories from | 34 author working on a single client machine; use of local repositories from |
33 multiple clients is not supported and may lead to confusing behaviour. | 35 multiple clients is not supported and may lead to confusing behaviour. |
34 | 36 |
37 The --switch flag specifies a particular charm URL to use. This is potentially | |
38 dangerous as the new charm may not be fully compatible with the old one. To | |
39 make it a little safer, the following checks are made: | |
40 | |
41 - The new charm must declare all relations | |
42 that the service is currently participating in. | |
43 | |
44 - The new charm must declare all the configuration | |
45 settings of the old charm and they must all have the same types | |
46 as the old charm. | |
rog
2013/04/26 15:06:33
probably worth reflowing all this text.
dimitern
2013/04/26 16:34:42
Done.
| |
47 | |
48 The new charm may add new relations and configuration settings. | |
49 | |
50 In addition, you can specify --revision to select a specific revision number | |
51 to upgrade to, rather than the newest one. This cannot be combined with --switch . | |
rog
2013/04/26 15:06:33
perhaps add:
To specify a given revision number w
dimitern
2013/04/26 16:34:42
Done.
| |
52 | |
35 Use of the --force flag is not generally recommended; units upgraded while in | 53 Use of the --force flag is not generally recommended; units upgraded while in |
36 an error state will not have upgrade-charm hooks executed, and may cause | 54 an error state will not have upgrade-charm hooks executed, and may cause |
37 unexpected behavior. | 55 unexpected behavior. |
38 ` | 56 ` |
39 | 57 |
40 func (c *UpgradeCharmCommand) Info() *cmd.Info { | 58 func (c *UpgradeCharmCommand) Info() *cmd.Info { |
41 return &cmd.Info{ | 59 return &cmd.Info{ |
42 Name: "upgrade-charm", | 60 Name: "upgrade-charm", |
43 Args: "<service>", | 61 Args: "<service>", |
44 Purpose: "upgrade a service's charm", | 62 Purpose: "upgrade a service's charm", |
45 Doc: upgradeCharmDoc, | 63 Doc: upgradeCharmDoc, |
46 } | 64 } |
47 } | 65 } |
48 | 66 |
49 func (c *UpgradeCharmCommand) SetFlags(f *gnuflag.FlagSet) { | 67 func (c *UpgradeCharmCommand) SetFlags(f *gnuflag.FlagSet) { |
50 c.EnvCommandBase.SetFlags(f) | 68 c.EnvCommandBase.SetFlags(f) |
51 f.BoolVar(&c.Force, "force", false, "upgrade all units immediately, even if in error state") | 69 f.BoolVar(&c.Force, "force", false, "upgrade all units immediately, even if in error state") |
52 f.StringVar(&c.RepoPath, "repository", os.Getenv("JUJU_REPOSITORY"), "lo cal charm repository path") | 70 f.StringVar(&c.RepoPath, "repository", os.Getenv("JUJU_REPOSITORY"), "lo cal charm repository path") |
71 f.StringVar(&c.SwitchURL, "switch", "", "charm URL to upgrade to") | |
72 f.IntVar(&c.Revision, "revision", -1, "revision number to upgrade to") | |
53 } | 73 } |
54 | 74 |
55 func (c *UpgradeCharmCommand) Init(args []string) error { | 75 func (c *UpgradeCharmCommand) Init(args []string) error { |
56 switch len(args) { | 76 switch len(args) { |
57 case 1: | 77 case 1: |
58 if !state.IsServiceName(args[0]) { | 78 if !state.IsServiceName(args[0]) { |
59 return fmt.Errorf("invalid service name %q", args[0]) | 79 return fmt.Errorf("invalid service name %q", args[0]) |
60 } | 80 } |
61 c.ServiceName = args[0] | 81 c.ServiceName = args[0] |
62 case 0: | 82 case 0: |
63 return errors.New("no service specified") | 83 return errors.New("no service specified") |
64 default: | 84 default: |
65 return cmd.CheckEmpty(args[1:]) | 85 return cmd.CheckEmpty(args[1:]) |
66 } | 86 } |
67 // TODO(dimitern): add the other flags --switch and --revision. | |
68 return nil | 87 return nil |
69 } | 88 } |
70 | 89 |
71 // Run connects to the specified environment and starts the charm | 90 // Run connects to the specified environment and starts the charm |
72 // upgrade process. | 91 // upgrade process. |
73 func (c *UpgradeCharmCommand) Run(ctx *cmd.Context) error { | 92 func (c *UpgradeCharmCommand) Run(ctx *cmd.Context) error { |
74 conn, err := juju.NewConnFromName(c.EnvName) | 93 conn, err := juju.NewConnFromName(c.EnvName) |
75 if err != nil { | 94 if err != nil { |
76 return err | 95 return err |
77 } | 96 } |
78 defer conn.Close() | 97 defer conn.Close() |
79 service, err := conn.State.Service(c.ServiceName) | 98 service, err := conn.State.Service(c.ServiceName) |
80 if err != nil { | 99 if err != nil { |
81 return err | 100 return err |
82 } | 101 } |
83 » curl, _ := service.CharmURL() | 102 » var curl *charm.URL |
103 » if c.SwitchURL != "" { | |
104 » » if c.Revision >= 0 { | |
105 » » » return fmt.Errorf("cannot specify --switch and --revisio n together") | |
106 » » } | |
107 » » var err error | |
108 » » conf, err := conn.State.EnvironConfig() | |
109 » » if err != nil { | |
110 » » » return err | |
111 » » } | |
112 » » curl, err = charm.InferURL(c.SwitchURL, conf.DefaultSeries()) | |
113 » » if err != nil { | |
114 » » » return err | |
115 » » } | |
116 » } else { | |
117 » » curl, _ = service.CharmURL() | |
118 » } | |
84 repo, err := charm.InferRepository(curl, ctx.AbsPath(c.RepoPath)) | 119 repo, err := charm.InferRepository(curl, ctx.AbsPath(c.RepoPath)) |
85 if err != nil { | 120 if err != nil { |
86 return err | 121 return err |
87 } | 122 } |
88 » rev, err := repo.Latest(curl) | 123 » latest, err := repo.Latest(curl) |
rog
2013/04/26 15:06:33
i think this still isn't quite right.
if someone s
dimitern
2013/04/26 16:37:19
Done.
| |
89 if err != nil { | 124 if err != nil { |
90 return err | 125 return err |
91 } | 126 } |
92 bumpRevision := false | 127 bumpRevision := false |
93 » if curl.Revision == rev { | 128 » rev := latest |
129 » if c.Revision >= 0 { | |
130 » » rev = c.Revision | |
131 » } else if curl.Revision == rev { | |
94 if _, isLocal := repo.(*charm.LocalRepository); !isLocal { | 132 if _, isLocal := repo.(*charm.LocalRepository); !isLocal { |
133 // This is not a local repository. | |
rog
2013/04/26 15:06:33
i think that's self evident from the condition on
dimitern
2013/04/26 16:34:42
Removed.
| |
95 return fmt.Errorf("already running latest charm %q", cur l) | 134 return fmt.Errorf("already running latest charm %q", cur l) |
96 } | 135 } |
97 // This is a local repository. | 136 // This is a local repository. |
98 if ch, err := repo.Get(curl); err != nil { | 137 if ch, err := repo.Get(curl); err != nil { |
99 return err | 138 return err |
100 } else if _, bumpRevision = ch.(*charm.Dir); !bumpRevision { | 139 } else if _, bumpRevision = ch.(*charm.Dir); !bumpRevision { |
101 // Only bump the revision when it's a directory. | 140 // Only bump the revision when it's a directory. |
102 return fmt.Errorf("already running latest charm %q", cur l) | 141 return fmt.Errorf("already running latest charm %q", cur l) |
103 } | 142 } |
104 } | 143 } |
105 sch, err := conn.PutCharm(curl.WithRevision(rev), repo, bumpRevision) | 144 sch, err := conn.PutCharm(curl.WithRevision(rev), repo, bumpRevision) |
106 if err != nil { | 145 if err != nil { |
107 return err | 146 return err |
108 } | 147 } |
109 return service.SetCharm(sch, c.Force) | 148 return service.SetCharm(sch, c.Force) |
110 } | 149 } |
OLD | NEW |