github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/model/addgeneration.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package model 5 6 import ( 7 "github.com/juju/cmd" 8 "github.com/juju/errors" 9 "github.com/juju/gnuflag" 10 11 "github.com/juju/juju/api/modelgeneration" 12 jujucmd "github.com/juju/juju/cmd" 13 "github.com/juju/juju/cmd/modelcmd" 14 "github.com/juju/juju/core/model" 15 ) 16 17 const ( 18 addGenerationSummary = "Adds a new generation to the model." 19 addGenerationDoc = ` 20 Users need to be able to roll changes to applications in a safe guided 21 processes that controls the flow such that not all units of an HA application 22 are hit at once. This also allows some manual canary testing and provides 23 control over the flow of changes out to the model. 24 25 Examples: 26 juju add-generation 27 28 See also: 29 advance-generation 30 cancel-generation 31 switch-generation 32 ` 33 ) 34 35 // NewAddGenerationCommand wraps addGenerationCommand with sane model settings. 36 func NewAddGenerationCommand() cmd.Command { 37 return modelcmd.Wrap(&addGenerationCommand{}) 38 } 39 40 // addGenerationCommand is the simplified command for accessing and setting 41 // attributes related to adding model generations. 42 type addGenerationCommand struct { 43 modelcmd.ModelCommandBase 44 45 api AddGenerationCommandAPI 46 } 47 48 // AddGenerationCommandAPI defines an API interface to be used during testing. 49 //go:generate mockgen -package mocks -destination ./mocks/addgeneration_mock.go github.com/juju/juju/cmd/juju/model AddGenerationCommandAPI 50 type AddGenerationCommandAPI interface { 51 Close() error 52 AddGeneration(string) error 53 } 54 55 // Info implements part of the cmd.Command interface. 56 func (c *addGenerationCommand) Info() *cmd.Info { 57 info := &cmd.Info{ 58 Name: "add-generation", 59 Purpose: addGenerationSummary, 60 Doc: addGenerationDoc, 61 } 62 return jujucmd.Info(info) 63 } 64 65 // SetFlags implements part of the cmd.Command interface. 66 func (c *addGenerationCommand) SetFlags(f *gnuflag.FlagSet) { 67 c.ModelCommandBase.SetFlags(f) 68 } 69 70 // Init implements part of the cmd.Command interface. 71 func (c *addGenerationCommand) Init(args []string) error { 72 if len(args) != 0 { 73 return errors.Errorf("No arguments allowed") 74 } 75 return nil 76 } 77 78 // getAPI returns the API. This allows passing in a test AddGenerationCommandAPI 79 // implementation. 80 func (c *addGenerationCommand) getAPI() (AddGenerationCommandAPI, error) { 81 if c.api != nil { 82 return c.api, nil 83 } 84 api, err := c.NewAPIRoot() 85 if err != nil { 86 return nil, errors.Annotate(err, "opening API connection") 87 } 88 client := modelgeneration.NewClient(api) 89 return client, nil 90 } 91 92 // Run implements the meaty part of the cmd.Command interface. 93 func (c *addGenerationCommand) Run(ctx *cmd.Context) error { 94 client, err := c.getAPI() 95 if err != nil { 96 return err 97 } 98 defer client.Close() 99 100 _, modelDetails, err := c.ModelCommandBase.ModelDetails() 101 if err != nil { 102 return errors.Annotate(err, "getting model details") 103 } 104 105 if err = client.AddGeneration(modelDetails.ModelUUID); err != nil { 106 return err 107 } 108 109 // Now update the model store with the 'next' generation for this 110 // model. 111 if err = c.SetModelGeneration(model.GenerationNext); err != nil { 112 return err 113 } 114 115 ctx.Stdout.Write([]byte("target generation set to next\n")) 116 return nil 117 }