github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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 "gopkg.in/juju/charm.v6" 14 "gopkg.in/juju/names.v2" 15 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/core/application" 18 "github.com/juju/juju/core/network" 19 "github.com/juju/juju/core/relation" 20 "github.com/juju/juju/storage" 21 ) 22 23 // Context is the interface that all hook helper commands 24 // depend on to interact with the rest of the system. 25 type Context interface { 26 HookContext 27 relationHookContext 28 actionHookContext 29 } 30 31 // HookContext represents the information and functionality that is 32 // common to all charm hooks. 33 type HookContext interface { 34 ContextUnit 35 ContextStatus 36 ContextInstance 37 ContextNetworking 38 ContextLeadership 39 ContextMetrics 40 ContextStorage 41 ContextComponents 42 ContextRelations 43 ContextVersion 44 } 45 46 // UnitHookContext is the context for a unit hook. 47 type UnitHookContext interface { 48 HookContext 49 } 50 51 // RelationHookContext is the context for a relation hook. 52 type RelationHookContext interface { 53 HookContext 54 relationHookContext 55 } 56 57 type relationHookContext interface { 58 // HookRelation returns the ContextRelation associated with the executing 59 // hook if it was found, or an error if it was not found (or is not available). 60 HookRelation() (ContextRelation, error) 61 62 // RemoteUnitName returns the name of the remote unit the hook execution 63 // is associated with if it was found, and an error if it was not found or is not 64 // available. 65 RemoteUnitName() (string, error) 66 } 67 68 // ActionHookContext is the context for an action hook. 69 type ActionHookContext interface { 70 HookContext 71 actionHookContext 72 } 73 74 type actionHookContext interface { 75 // ActionParams returns the map of params passed with an Action. 76 ActionParams() (map[string]interface{}, error) 77 78 // UpdateActionResults inserts new values for use with action-set. 79 // The results struct will be delivered to the controller upon 80 // completion of the Action. 81 UpdateActionResults(keys []string, value string) error 82 83 // SetActionMessage sets a message for the Action. 84 SetActionMessage(string) error 85 86 // SetActionFailed sets a failure state for the Action. 87 SetActionFailed() error 88 } 89 90 // ContextUnit is the part of a hook context related to the unit. 91 type ContextUnit interface { 92 // UnitName returns the executing unit's name. 93 UnitName() string 94 95 // Config returns the current application configuration of the executing unit. 96 ConfigSettings() (charm.Settings, error) 97 98 // GoalState returns the goal state for the current unit. 99 GoalState() (*application.GoalState, error) 100 101 // SetPodSpec updates the yaml spec used to create a pod. 102 SetPodSpec(specYaml string) error 103 104 // CloudSpec returns the unit's cloud specification 105 CloudSpec() (*params.CloudSpec, error) 106 } 107 108 // ContextStatus is the part of a hook context related to the unit's status. 109 type ContextStatus interface { 110 // UnitStatus returns the executing unit's current status. 111 UnitStatus() (*StatusInfo, error) 112 113 // SetUnitStatus updates the unit's status. 114 SetUnitStatus(StatusInfo) error 115 116 // ApplicationStatus returns the executing unit's application status 117 // (including all units). 118 ApplicationStatus() (ApplicationStatusInfo, error) 119 120 // SetApplicationStatus updates the status for the unit's application. 121 SetApplicationStatus(StatusInfo) error 122 } 123 124 // RebootPriority is the type used for reboot requests. 125 type RebootPriority int 126 127 // ContextInstance is the part of a hook context related to the unit's instance. 128 type ContextInstance interface { 129 // AvailabilityZone returns the executing unit's availability zone or an error 130 // if it was not found (or is not available). 131 AvailabilityZone() (string, error) 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 or an 141 // error if it is not available. 142 PublicAddress() (string, error) 143 144 // PrivateAddress returns the executing unit's private address or an 145 // error if it is not available. 146 PrivateAddress() (string, error) 147 148 // OpenPorts marks the supplied port range for opening when the 149 // executing unit's application is exposed. 150 OpenPorts(protocol string, fromPort, toPort int) error 151 152 // ClosePorts ensures the supplied port range is closed even when 153 // the executing unit's application is exposed (unless it is opened 154 // separately by a co- located unit). 155 ClosePorts(protocol string, fromPort, toPort int) error 156 157 // OpenedPorts returns all port ranges currently opened by this 158 // unit on its assigned machine. The result is sorted first by 159 // protocol, then by number. 160 OpenedPorts() []network.PortRange 161 162 // NetworkInfo returns the network info for the given bindings on the given relation. 163 NetworkInfo(bindingNames []string, relationId int) (map[string]params.NetworkInfoResult, error) 164 } 165 166 // ContextLeadership is the part of a hook context related to the 167 // unit leadership. 168 type ContextLeadership interface { 169 // IsLeader returns true if the local unit is known to be leader for at 170 // least the next 30s. 171 IsLeader() (bool, error) 172 173 // LeaderSettings returns the current leader settings. Once leader settings 174 // have been read in a given context, they will not be updated other than 175 // via successful calls to WriteLeaderSettings. 176 LeaderSettings() (map[string]string, error) 177 178 // WriteLeaderSettings writes the supplied settings directly to state, or 179 // fails if the local unit is not the application's leader. 180 WriteLeaderSettings(map[string]string) error 181 } 182 183 // ContextMetrics is the part of a hook context related to metrics. 184 type ContextMetrics interface { 185 // AddMetric records a metric to return after hook execution. 186 AddMetric(string, string, time.Time) error 187 // AddMetricLabels records a metric with tags to return after hook execution. 188 AddMetricLabels(string, string, time.Time, map[string]string) error 189 } 190 191 // ContextStorage is the part of a hook context related to storage 192 // resources associated with the unit. 193 type ContextStorage interface { 194 // StorageTags returns a list of tags for storage instances 195 // attached to the unit or an error if they are not available. 196 StorageTags() ([]names.StorageTag, error) 197 198 // Storage returns the ContextStorageAttachment with the supplied 199 // tag if it was found, and an error if it was not found or is not 200 // available to the context. 201 Storage(names.StorageTag) (ContextStorageAttachment, error) 202 203 // HookStorage returns the storage attachment associated 204 // the executing hook if it was found, and an error if it 205 // was not found or is not available. 206 HookStorage() (ContextStorageAttachment, error) 207 208 // AddUnitStorage saves storage constraints in the context. 209 AddUnitStorage(map[string]params.StorageConstraints) error 210 } 211 212 // ContextComponents exposes modular Juju components as they relate to 213 // the unit in the context of the hook. 214 type ContextComponents interface { 215 // Component returns the ContextComponent with the supplied name if 216 // it was found. 217 Component(name string) (ContextComponent, error) 218 } 219 220 // ContextRelations exposes the relations associated with the unit. 221 type ContextRelations interface { 222 // Relation returns the relation with the supplied id if it was found, and 223 // an error if it was not found or is not available. 224 Relation(id int) (ContextRelation, error) 225 226 // RelationIds returns the ids of all relations the executing unit is 227 // currently participating in or an error if they are not available. 228 RelationIds() ([]int, error) 229 } 230 231 // ContextComponent is a single modular Juju component as it relates to 232 // the current unit and hook. Components should implement this interfaces 233 // in a type-safe way. Ensuring checked type-conversions are preformed on 234 // the result and value interfaces. You will use the runner.RegisterComponentFunc 235 // to register a your components concrete ContextComponent implementation. 236 // 237 // See: process/context/context.go for an implementation example. 238 // 239 type ContextComponent interface { 240 // Flush pushes the component's data to Juju state. 241 // In the Flush implementation, call your components API. 242 Flush() error 243 } 244 245 // ContextRelation expresses the capabilities of a hook with respect to a relation. 246 //go:generate mockgen -package jujuc -destination context_mock_test.go github.com/juju/juju/worker/uniter/runner/jujuc ContextRelation 247 type ContextRelation interface { 248 249 // Id returns an integer which uniquely identifies the relation. 250 Id() int 251 252 // Name returns the name the locally executing charm assigned to this relation. 253 Name() string 254 255 // FakeId returns a string of the form "relation-name:123", which uniquely 256 // identifies the relation to the hook. In reality, the identification 257 // of the relation is the integer following the colon, but the composed 258 // name is useful to humans observing it. 259 FakeId() string 260 261 // Settings allows read/write access to the local unit's settings in 262 // this relation. 263 Settings() (Settings, error) 264 265 // UnitNames returns a list of the remote units in the relation. 266 UnitNames() []string 267 268 // ReadSettings returns the settings of any remote unit in the relation. 269 ReadSettings(unit string) (params.Settings, error) 270 271 // Suspended returns true if the relation is suspended. 272 Suspended() bool 273 274 // SetStatus sets the relation's status. 275 SetStatus(relation.Status) error 276 } 277 278 // ContextStorageAttachment expresses the capabilities of a hook with 279 // respect to a storage attachment. 280 type ContextStorageAttachment interface { 281 282 // Tag returns a tag which uniquely identifies the storage attachment 283 // in the context of the unit. 284 Tag() names.StorageTag 285 286 // Kind returns the kind of the storage. 287 Kind() storage.StorageKind 288 289 // Location returns the location of the storage: the mount point for 290 // filesystem-kind stores, and the device path for block-kind stores. 291 Location() string 292 } 293 294 // ContextVersion expresses the parts of a hook context related to 295 // reporting workload versions. 296 type ContextVersion interface { 297 298 // UnitWorkloadVersion returns the currently set workload version for 299 // the unit. 300 UnitWorkloadVersion() (string, error) 301 302 // SetUnitWorkloadVersion updates the workload version for the unit. 303 SetUnitWorkloadVersion(string) error 304 } 305 306 // Settings is implemented by types that manipulate unit settings. 307 type Settings interface { 308 Map() params.Settings 309 Set(string, string) 310 Delete(string) 311 } 312 313 // NewRelationIdValue returns a gnuflag.Value for convenient parsing of relation 314 // ids in ctx. 315 func NewRelationIdValue(ctx Context, result *int) (*relationIdValue, error) { 316 v := &relationIdValue{result: result, ctx: ctx} 317 id := -1 318 if r, err := ctx.HookRelation(); err == nil { 319 id = r.Id() 320 v.value = r.FakeId() 321 } else if !errors.IsNotFound(err) { 322 return nil, errors.Trace(err) 323 } 324 *result = id 325 return v, nil 326 } 327 328 // relationIdValue implements gnuflag.Value for use in relation commands. 329 type relationIdValue struct { 330 result *int 331 ctx Context 332 value string 333 } 334 335 // String returns the current value. 336 func (v *relationIdValue) String() string { 337 return v.value 338 } 339 340 // Set interprets value as a relation id, if possible, and returns an error 341 // if it is not known to the system. The parsed relation id will be written 342 // to v.result. 343 func (v *relationIdValue) Set(value string) error { 344 trim := value 345 if idx := strings.LastIndex(trim, ":"); idx != -1 { 346 trim = trim[idx+1:] 347 } 348 id, err := strconv.Atoi(trim) 349 if err != nil { 350 return fmt.Errorf("invalid relation id") 351 } 352 if _, err := v.ctx.Relation(id); err != nil { 353 return errors.Trace(err) 354 } 355 *v.result = id 356 v.value = value 357 return nil 358 }