-
Notifications
You must be signed in to change notification settings - Fork 491
/
removerelation.go
159 lines (137 loc) · 4.71 KB
/
removerelation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package application
import (
"strconv"
"time"
"github.com/juju/cmd/v3"
"github.com/juju/errors"
"github.com/juju/gnuflag"
"github.com/juju/juju/api/client/application"
jujucmd "github.com/juju/juju/cmd"
"github.com/juju/juju/cmd/juju/block"
"github.com/juju/juju/cmd/modelcmd"
)
var helpSummary = `
Removes an existing relation between two applications.`[1:]
var helpDetails = `
An existing relation between the two specified applications will be removed.
This should not result in either of the applications entering an error state,
but may result in either or both of the applications being unable to continue
normal operation. In the case that there is more than one relation between
two applications it is necessary to specify which is to be removed (see
examples). Relations will automatically be removed when using the`[1:] + "`juju\nremove-application`" + ` command.
The relation is specified using the relation endpoint names, eg
mysql wordpress, or
mediawiki:db mariadb:db
It is also possible to specify the relation ID, if known. This is useful to
terminate a relation originating from a different model, where only the ID is known.
Sometimes, the removal of the relation may fail as Juju encounters errors
and failures that need to be dealt with before a relation can be removed.
However, at times, there is a need to remove a relation ignoring
all operational errors. In these rare cases, use --force option but note
that --force will remove a relation without giving it the opportunity to be removed cleanly.
`
const helpExamples = `
juju remove-relation mysql wordpress
juju remove-relation 4
juju remove-relation 4 --force
In the case of multiple relations, the relation name should be specified
at least once - the following examples will all have the same effect:
juju remove-relation mediawiki:db mariadb:db
juju remove-relation mediawiki mariadb:db
juju remove-relation mediawiki:db mariadb
`
// NewRemoveRelationCommand returns a command to remove a relation between 2 applications.
func NewRemoveRelationCommand() cmd.Command {
command := &removeRelationCommand{}
command.newAPIFunc = func() (ApplicationDestroyRelationAPI, error) {
root, err := command.NewAPIRoot()
if err != nil {
return nil, errors.Trace(err)
}
return application.NewClient(root), nil
}
return modelcmd.Wrap(command)
}
// removeRelationCommand causes an existing application relation to be shut down.
type removeRelationCommand struct {
modelcmd.ModelCommandBase
RelationId int
Endpoints []string
newAPIFunc func() (ApplicationDestroyRelationAPI, error)
Force bool
NoWait bool
fs *gnuflag.FlagSet
}
func (c *removeRelationCommand) Info() *cmd.Info {
return jujucmd.Info(&cmd.Info{
Name: "remove-relation",
Args: "<application1>[:<relation name1>] <application2>[:<relation name2>] | <relation-id>",
Purpose: helpSummary,
Doc: helpDetails,
Examples: helpExamples,
SeeAlso: []string{
"integrate",
"remove-application",
},
})
}
func (c *removeRelationCommand) Init(args []string) (err error) {
if len(args) == 1 {
if c.RelationId, err = strconv.Atoi(args[0]); err != nil || c.RelationId < 0 {
return errors.NotValidf("relation ID %q", args[0])
}
return nil
}
if len(args) != 2 {
return errors.Errorf("a relation must involve two applications")
}
c.Endpoints = args
return nil
}
func (c *removeRelationCommand) SetFlags(f *gnuflag.FlagSet) {
c.ModelCommandBase.SetFlags(f)
f.BoolVar(&c.Force, "force", false, "Force remove a relation")
c.fs = f
}
// ApplicationDestroyRelationAPI defines the API methods that application remove relation command uses.
type ApplicationDestroyRelationAPI interface {
Close() error
DestroyRelation(force *bool, maxWait *time.Duration, endpoints ...string) error
DestroyRelationId(relationId int, force *bool, maxWait *time.Duration) error
}
func (c *removeRelationCommand) Run(_ *cmd.Context) error {
noWaitSet := false
forceSet := false
c.fs.Visit(func(flag *gnuflag.Flag) {
if flag.Name == "no-wait" {
noWaitSet = true
} else if flag.Name == "force" {
forceSet = true
}
})
if !forceSet && noWaitSet {
return errors.NotValidf("--no-wait without --force")
}
var maxWait *time.Duration
var force *bool
if c.Force {
force = &c.Force
if c.NoWait {
zeroSec := 0 * time.Second
maxWait = &zeroSec
}
}
client, err := c.newAPIFunc()
if err != nil {
return err
}
defer client.Close()
if len(c.Endpoints) > 0 {
err = client.DestroyRelation(force, maxWait, c.Endpoints...)
} else {
err = client.DestroyRelationId(c.RelationId, force, maxWait)
}
return block.ProcessBlockedError(err, block.BlockRemove)
}