github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/application/setseries.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package application 5 6 import ( 7 "github.com/juju/cmd" 8 "github.com/juju/errors" 9 "github.com/juju/gnuflag" 10 "github.com/juju/utils/series" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/api" 14 "github.com/juju/juju/api/application" 15 "github.com/juju/juju/apiserver/params" 16 jujucmd "github.com/juju/juju/cmd" 17 "github.com/juju/juju/cmd/juju/block" 18 "github.com/juju/juju/cmd/modelcmd" 19 ) 20 21 // NewSetSeriesCommand returns a command which updates the series of 22 // an application. 23 func NewSetSeriesCommand() cmd.Command { 24 return modelcmd.Wrap(&setSeriesCommand{}) 25 } 26 27 // setSeriesAPI defines a subset of the application facade, as required 28 // by the set-series command. 29 type setSeriesAPI interface { 30 BestAPIVersion() int 31 Close() error 32 UpdateApplicationSeries(string, string, bool) error 33 } 34 35 // setSeriesCommand is responsible for updating the series of an application or machine. 36 type setSeriesCommand struct { 37 modelcmd.ModelCommandBase 38 modelcmd.IAASOnlyCommand 39 40 setSeriesClient setSeriesAPI 41 42 applicationName string 43 force bool 44 series string 45 } 46 47 var setSeriesDoc = ` 48 When no options are set, an application series value will be set within juju. 49 50 The update is disallowed unless the --force option is used if the requested 51 series is not explicitly supported by the application's charm and all 52 subordinates, as well as any other charms which may be deployed to the same 53 machine. 54 55 Examples: 56 juju set-series <application> <series> 57 juju set-series <application> <series> --force 58 59 See also: 60 status 61 upgrade-charm 62 ` 63 64 func (c *setSeriesCommand) Info() *cmd.Info { 65 return jujucmd.Info(&cmd.Info{ 66 Name: "set-series", 67 Args: "<application> <series>", 68 Purpose: "Set an application's series.", 69 Doc: setSeriesDoc, 70 }) 71 } 72 73 func (c *setSeriesCommand) SetFlags(f *gnuflag.FlagSet) { 74 c.ModelCommandBase.SetFlags(f) 75 f.BoolVar(&c.force, "force", false, "Set even if the series is not supported by the charm and/or related subordinate charms.") 76 } 77 78 // Init implements cmd.Command. 79 func (c *setSeriesCommand) Init(args []string) error { 80 switch len(args) { 81 case 2: 82 if names.IsValidApplication(args[0]) { 83 c.applicationName = args[0] 84 } else { 85 return errors.Errorf("invalid application name %q", args[0]) 86 } 87 if _, err := series.GetOSFromSeries(args[1]); err != nil { 88 return errors.Errorf("invalid series %q", args[1]) 89 } 90 c.series = args[1] 91 case 1: 92 if _, err := series.GetOSFromSeries(args[0]); err != nil { 93 return errors.Errorf("no series specified") 94 } else { 95 return errors.Errorf("no application name") 96 } 97 case 0: 98 return errors.Errorf("application name and series required") 99 default: 100 return cmd.CheckEmpty(args[2:]) 101 } 102 return nil 103 } 104 105 // Run implements cmd.Run. 106 func (c *setSeriesCommand) Run(ctx *cmd.Context) error { 107 var apiRoot api.Connection 108 if c.setSeriesClient == nil { 109 var err error 110 apiRoot, err = c.NewAPIRoot() 111 if err != nil { 112 return errors.Trace(err) 113 } 114 defer apiRoot.Close() 115 } 116 117 if c.applicationName != "" { 118 if c.setSeriesClient == nil { 119 c.setSeriesClient = application.NewClient(apiRoot) 120 defer c.setSeriesClient.Close() 121 } 122 if c.setSeriesClient.BestAPIVersion() < 5 { 123 return errors.New("setting the application series is not supported by this API server") 124 } 125 return c.updateApplicationSeries() 126 } 127 128 // This should never happen... 129 return errors.New("no application nor machine name specified") 130 } 131 132 func (c *setSeriesCommand) updateApplicationSeries() error { 133 err := block.ProcessBlockedError( 134 c.setSeriesClient.UpdateApplicationSeries(c.applicationName, c.series, c.force), 135 block.BlockChange) 136 137 if params.IsCodeIncompatibleSeries(err) { 138 return errors.Errorf("%v. Use --force to set the series anyway.", err) 139 } 140 return err 141 }