github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/uniter/runner/jujuc/context.go (about) 1 // Copyright 2012, 2013, 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package jujuc 5 6 import ( 7 "fmt" 8 "strconv" 9 "strings" 10 "time" 11 12 "github.com/juju/errors" 13 "github.com/juju/names" 14 "gopkg.in/juju/charm.v5" 15 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/network" 18 "github.com/juju/juju/storage" 19 ) 20 21 // RebootPriority is the type used for reboot requests. 22 type RebootPriority int 23 24 const ( 25 // RebootSkip is a noop. 26 RebootSkip RebootPriority = iota 27 // RebootAfterHook means wait for current hook to finish before 28 // rebooting. 29 RebootAfterHook 30 // RebootNow means reboot immediately, killing and requeueing the 31 // calling hook 32 RebootNow 33 ) 34 35 // Context is the interface that all hook helper commands 36 // depend on to interact with the rest of the system. 37 type Context interface { 38 HookContext 39 relationHookContext 40 actionHookContext 41 } 42 43 // HookContext represents the information and functionality that is 44 // common to all charm hooks. 45 type HookContext interface { 46 ContextUnit 47 ContextStatus 48 ContextInstance 49 ContextNetworking 50 ContextLeadership 51 ContextMetrics 52 ContextStorage 53 ContextRelations 54 } 55 56 // UnitHookContext is the context for a unit hook. 57 type UnitHookContext interface { 58 HookContext 59 } 60 61 // RelationHookContext is the context for a relation hook. 62 type RelationHookContext interface { 63 HookContext 64 relationHookContext 65 } 66 67 type relationHookContext interface { 68 // HookRelation returns the ContextRelation associated with the executing 69 // hook if it was found, and whether it was found. 70 HookRelation() (ContextRelation, bool) 71 72 // RemoteUnitName returns the name of the remote unit the hook execution 73 // is associated with if it was found, and whether it was found. 74 RemoteUnitName() (string, bool) 75 } 76 77 // ActionHookContext is the context for an action hook. 78 type ActionHookContext interface { 79 HookContext 80 actionHookContext 81 } 82 83 type actionHookContext interface { 84 // ActionParams returns the map of params passed with an Action. 85 ActionParams() (map[string]interface{}, error) 86 87 // UpdateActionResults inserts new values for use with action-set. 88 // The results struct will be delivered to the state server upon 89 // completion of the Action. 90 UpdateActionResults(keys []string, value string) error 91 92 // SetActionMessage sets a message for the Action. 93 SetActionMessage(string) error 94 95 // SetActionFailed sets a failure state for the Action. 96 SetActionFailed() error 97 } 98 99 // ContextUnit is the part of a hook context related to the unit. 100 type ContextUnit interface { 101 // UnitName returns the executing unit's name. 102 UnitName() string 103 104 // OwnerTag returns the user tag of the service the executing 105 // units belongs to. 106 OwnerTag() string 107 108 // Config returns the current service configuration of the executing unit. 109 ConfigSettings() (charm.Settings, error) 110 } 111 112 // ContextStatus is the part of a hook context related to the unit's status. 113 type ContextStatus interface { 114 // UnitStatus returns the executing unit's current status. 115 UnitStatus() (*StatusInfo, error) 116 117 // SetUnitStatus updates the unit's status. 118 SetUnitStatus(StatusInfo) error 119 120 // ServiceStatus returns the executing unit's service status 121 // (including all units). 122 ServiceStatus() (ServiceStatusInfo, error) 123 124 // SetServiceStatus updates the status for the unit's service. 125 SetServiceStatus(StatusInfo) error 126 } 127 128 // ContextInstance is the part of a hook context related to the unit's intance. 129 type ContextInstance interface { 130 // AvailabilityZone returns the executing unit's availablilty zone. 131 AvailabilityZone() (string, bool) 132 133 // RequestReboot will set the reboot flag to true on the machine agent 134 RequestReboot(prio RebootPriority) error 135 } 136 137 // ContextNetworking is the part of a hook context related to network 138 // interface of the unit's instance. 139 type ContextNetworking interface { 140 // PublicAddress returns the executing unit's public address. 141 PublicAddress() (string, bool) 142 143 // PrivateAddress returns the executing unit's private address. 144 PrivateAddress() (string, bool) 145 146 // OpenPorts marks the supplied port range for opening when the 147 // executing unit's service is exposed. 148 OpenPorts(protocol string, fromPort, toPort int) error 149 150 // ClosePorts ensures the supplied port range is closed even when 151 // the executing unit's service is exposed (unless it is opened 152 // separately by a co- located unit). 153 ClosePorts(protocol string, fromPort, toPort int) error 154 155 // OpenedPorts returns all port ranges currently opened by this 156 // unit on its assigned machine. The result is sorted first by 157 // protocol, then by number. 158 OpenedPorts() []network.PortRange 159 } 160 161 // ContextLeadership is the part of a hook context related to the 162 // unit leadership. 163 type ContextLeadership interface { 164 // IsLeader returns true if the local unit is known to be leader for at 165 // least the next 30s. 166 IsLeader() (bool, error) 167 168 // LeaderSettings returns the current leader settings. Once leader settings 169 // have been read in a given context, they will not be updated other than 170 // via successful calls to WriteLeaderSettings. 171 LeaderSettings() (map[string]string, error) 172 173 // WriteLeaderSettings writes the supplied settings directly to state, or 174 // fails if the local unit is not the service's leader. 175 WriteLeaderSettings(map[string]string) error 176 } 177 178 // ContextMetrics is the part of a hook context related to metrics. 179 type ContextMetrics interface { 180 // AddMetric records a metric to return after hook execution. 181 AddMetric(string, string, time.Time) error 182 } 183 184 // ContextStorage is the part of a hook context related to storage 185 // resources associated with the unit. 186 type ContextStorage interface { 187 // Storage returns the ContextStorageAttachment with the supplied 188 // tag if it was found, and whether it was found. 189 Storage(names.StorageTag) (ContextStorageAttachment, bool) 190 191 // HookStorage returns the storage attachment associated 192 // the executing hook if it was found, and whether it was found. 193 HookStorage() (ContextStorageAttachment, bool) 194 195 // AddUnitStorage saves storage constraints in the context. 196 AddUnitStorage(map[string]params.StorageConstraints) 197 } 198 199 // ContextRelations exposes the relations associated with the unit. 200 type ContextRelations interface { 201 // Relation returns the relation with the supplied id if it was found, and 202 // whether it was found. 203 Relation(id int) (ContextRelation, bool) 204 205 // RelationIds returns the ids of all relations the executing unit is 206 // currently participating in. 207 RelationIds() []int 208 } 209 210 // ContextRelation expresses the capabilities of a hook with respect to a relation. 211 type ContextRelation interface { 212 213 // Id returns an integer which uniquely identifies the relation. 214 Id() int 215 216 // Name returns the name the locally executing charm assigned to this relation. 217 Name() string 218 219 // FakeId returns a string of the form "relation-name:123", which uniquely 220 // identifies the relation to the hook. In reality, the identification 221 // of the relation is the integer following the colon, but the composed 222 // name is useful to humans observing it. 223 FakeId() string 224 225 // Settings allows read/write access to the local unit's settings in 226 // this relation. 227 Settings() (Settings, error) 228 229 // UnitNames returns a list of the remote units in the relation. 230 UnitNames() []string 231 232 // ReadSettings returns the settings of any remote unit in the relation. 233 ReadSettings(unit string) (params.Settings, error) 234 } 235 236 // ContextStorageAttachment expresses the capabilities of a hook with 237 // respect to a storage attachment. 238 type ContextStorageAttachment interface { 239 240 // Tag returns a tag which uniquely identifies the storage attachment 241 // in the context of the unit. 242 Tag() names.StorageTag 243 244 // Kind returns the kind of the storage. 245 Kind() storage.StorageKind 246 247 // Location returns the location of the storage: the mount point for 248 // filesystem-kind stores, and the device path for block-kind stores. 249 Location() string 250 } 251 252 // Settings is implemented by types that manipulate unit settings. 253 type Settings interface { 254 Map() params.Settings 255 Set(string, string) 256 Delete(string) 257 } 258 259 // newRelationIdValue returns a gnuflag.Value for convenient parsing of relation 260 // ids in ctx. 261 func newRelationIdValue(ctx Context, result *int) *relationIdValue { 262 v := &relationIdValue{result: result, ctx: ctx} 263 id := -1 264 if r, found := ctx.HookRelation(); found { 265 id = r.Id() 266 v.value = r.FakeId() 267 } 268 *result = id 269 return v 270 } 271 272 // relationIdValue implements gnuflag.Value for use in relation commands. 273 type relationIdValue struct { 274 result *int 275 ctx Context 276 value string 277 } 278 279 // String returns the current value. 280 func (v *relationIdValue) String() string { 281 return v.value 282 } 283 284 // Set interprets value as a relation id, if possible, and returns an error 285 // if it is not known to the system. The parsed relation id will be written 286 // to v.result. 287 func (v *relationIdValue) Set(value string) error { 288 trim := value 289 if idx := strings.LastIndex(trim, ":"); idx != -1 { 290 trim = trim[idx+1:] 291 } 292 id, err := strconv.Atoi(trim) 293 if err != nil { 294 return fmt.Errorf("invalid relation id") 295 } 296 if _, found := v.ctx.Relation(id); !found { 297 return fmt.Errorf("unknown relation id") 298 } 299 *v.result = id 300 v.value = value 301 return nil 302 } 303 304 // newStorageIdValue returns a gnuflag.Value for convenient parsing of storage 305 // ids in ctx. 306 func newStorageIdValue(ctx Context, result *names.StorageTag) *storageIdValue { 307 v := &storageIdValue{result: result, ctx: ctx} 308 if s, found := ctx.HookStorage(); found { 309 *v.result = s.Tag() 310 } 311 return v 312 } 313 314 // storageIdValue implements gnuflag.Value for use in storage commands. 315 type storageIdValue struct { 316 result *names.StorageTag 317 ctx Context 318 } 319 320 // String returns the current value. 321 func (v *storageIdValue) String() string { 322 if *v.result == (names.StorageTag{}) { 323 return "" 324 } 325 return v.result.Id() 326 } 327 328 // Set interprets value as a storage id, if possible, and returns an error 329 // if it is not known to the system. The parsed storage id will be written 330 // to v.result. 331 func (v *storageIdValue) Set(value string) error { 332 if !names.IsValidStorage(value) { 333 return errors.Errorf("invalid storage ID %q", value) 334 } 335 tag := names.NewStorageTag(value) 336 if _, found := v.ctx.Storage(tag); !found { 337 return fmt.Errorf("unknown storage ID") 338 } 339 *v.result = tag 340 return nil 341 }