github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/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/charm/v12" 13 "github.com/juju/errors" 14 "github.com/juju/loggo" 15 "github.com/juju/names/v5" 16 17 "github.com/juju/juju/core/application" 18 "github.com/juju/juju/core/life" 19 "github.com/juju/juju/core/network" 20 "github.com/juju/juju/core/payloads" 21 "github.com/juju/juju/core/relation" 22 "github.com/juju/juju/core/secrets" 23 "github.com/juju/juju/rpc/params" 24 "github.com/juju/juju/storage" 25 ) 26 27 // Context is the interface that all hook helper commands 28 // depend on to interact with the rest of the system. 29 // 30 //go:generate go run go.uber.org/mock/mockgen -package mocks -destination mocks/context_mock.go github.com/juju/juju/worker/uniter/runner/jujuc Context 31 type Context interface { 32 HookContext 33 relationHookContext 34 actionHookContext 35 unitCharmStateContext 36 workloadHookContext 37 } 38 39 // HookContext represents the information and functionality that is 40 // common to all charm hooks. 41 type HookContext interface { 42 ContextUnit 43 ContextStatus 44 ContextInstance 45 ContextNetworking 46 ContextLeadership 47 ContextMetrics 48 ContextStorage 49 ContextResources 50 ContextPayloads 51 ContextRelations 52 ContextVersion 53 ContextSecrets 54 55 // GetLogger returns a juju loggo Logger for the supplied module that is 56 // correctly wired up for the given context 57 GetLogger(module string) loggo.Logger 58 } 59 60 // UnitHookContext is the context for a unit hook. 61 type UnitHookContext interface { 62 HookContext 63 } 64 65 // RelationHookContext is the context for a relation hook. 66 type RelationHookContext interface { 67 HookContext 68 relationHookContext 69 } 70 71 type relationHookContext interface { 72 // HookRelation returns the ContextRelation associated with the executing 73 // hook if it was found, or an error if it was not found (or is not available). 74 HookRelation() (ContextRelation, error) 75 76 // RemoteUnitName returns the name of the remote unit the hook execution 77 // is associated with if it was found, and an error if it was not found or is not 78 // available. 79 RemoteUnitName() (string, error) 80 81 // RemoteApplicationName returns the name of the remote application the hook execution 82 // is associated with if it was found, and an error if it was not found or is not 83 // available. 84 RemoteApplicationName() (string, error) 85 } 86 87 // ActionHookContext is the context for an action hook. 88 type ActionHookContext interface { 89 HookContext 90 actionHookContext 91 } 92 93 type actionHookContext interface { 94 // ActionParams returns the map of params passed with an Action. 95 ActionParams() (map[string]interface{}, error) 96 97 // UpdateActionResults inserts new values for use with action-set. 98 // The results struct will be delivered to the controller upon 99 // completion of the Action. 100 UpdateActionResults(keys []string, value interface{}) error 101 102 // SetActionMessage sets a message for the Action. 103 SetActionMessage(string) error 104 105 // SetActionFailed sets a failure state for the Action. 106 SetActionFailed() error 107 108 // LogActionMessage records a progress message for the Action. 109 LogActionMessage(string) error 110 } 111 112 // WorkloadHookContext is the context for a workload hook. 113 type WorkloadHookContext interface { 114 HookContext 115 workloadHookContext 116 } 117 118 type workloadHookContext interface { 119 // WorkloadName returns the name of the container/workload for workload hooks. 120 WorkloadName() (string, error) 121 } 122 123 // unitCharmStateContext provides helper for interacting with the charm state 124 // that is stored within the context. 125 type unitCharmStateContext interface { 126 // GetCharmState returns a copy of the charm state. 127 GetCharmState() (map[string]string, error) 128 129 // GetCharmStateValue returns the value of the given key. 130 GetCharmStateValue(string) (string, error) 131 132 // DeleteCharmStateValue deletes the key/value pair for the given key. 133 DeleteCharmStateValue(string) error 134 135 // SetCharmStateValue sets the key to the specified value. 136 SetCharmStateValue(string, string) error 137 } 138 139 // ContextUnit is the part of a hook context related to the unit. 140 type ContextUnit interface { 141 // UnitName returns the executing unit's name. 142 UnitName() string 143 144 // ConfigSettings returns the current application 145 // configuration of the executing unit. 146 ConfigSettings() (charm.Settings, error) 147 148 // GoalState returns the goal state for the current unit. 149 GoalState() (*application.GoalState, error) 150 151 // SetPodSpec updates the yaml spec used to create a pod. 152 // TODO(wallyworld) - rename to SetK8sSpec (here and elsewhere) 153 SetPodSpec(specYaml string) error 154 155 // GetPodSpec returns the yaml spec used to create a pod. 156 // TODO(wallyworld) - rename to GetK8sSpec (here and elsewhere) 157 GetPodSpec() (string, error) 158 159 // SetRawK8sSpec updates the raw yaml spec used to create a pod. 160 SetRawK8sSpec(specYaml string) error 161 162 // GetRawK8sSpec returns the raw yaml spec used to create a pod. 163 GetRawK8sSpec() (string, error) 164 165 // CloudSpec returns the unit's cloud specification 166 CloudSpec() (*params.CloudSpec, error) 167 } 168 169 // SecretCreateArgs specifies args used to create a secret. 170 // Nil values are not included in the create. 171 type SecretCreateArgs struct { 172 SecretUpdateArgs 173 174 OwnerTag names.Tag 175 } 176 177 // SecretUpdateArgs specifies args used to update a secret. 178 // Nil values are not included in the update. 179 type SecretUpdateArgs struct { 180 // Value is the new secret value or nil to not update. 181 Value secrets.SecretValue 182 183 RotatePolicy *secrets.RotatePolicy 184 ExpireTime *time.Time 185 186 Description *string 187 Label *string 188 } 189 190 // SecretGrantRevokeArgs specify the args used to grant or revoke access to a secret. 191 type SecretGrantRevokeArgs struct { 192 ApplicationName *string 193 UnitName *string 194 RelationKey *string 195 Role *secrets.SecretRole 196 } 197 198 // SecretMetadata holds a secret's metadata. 199 type SecretMetadata struct { 200 Owner names.Tag 201 Description string 202 Label string 203 RotatePolicy secrets.RotatePolicy 204 LatestRevision int 205 LatestExpireTime *time.Time 206 NextRotateTime *time.Time 207 Revisions []int 208 Access []secrets.AccessInfo 209 } 210 211 // ContextSecrets is the part of a hook context related to secrets. 212 type ContextSecrets interface { 213 // GetSecret returns the value of the specified secret. 214 GetSecret(*secrets.URI, string, bool, bool) (secrets.SecretValue, error) 215 216 // CreateSecret creates a secret with the specified data. 217 CreateSecret(*SecretCreateArgs) (*secrets.URI, error) 218 219 // UpdateSecret creates a secret with the specified data. 220 UpdateSecret(*secrets.URI, *SecretUpdateArgs) error 221 222 // RemoveSecret removes a secret with the specified uri. 223 RemoveSecret(*secrets.URI, *int) error 224 225 // GrantSecret grants access to the specified secret. 226 GrantSecret(*secrets.URI, *SecretGrantRevokeArgs) error 227 228 // RevokeSecret revokes access to the specified secret. 229 RevokeSecret(*secrets.URI, *SecretGrantRevokeArgs) error 230 231 // SecretMetadata gets the secret metadata for secrets created by the charm. 232 SecretMetadata() (map[string]SecretMetadata, error) 233 } 234 235 // ContextStatus is the part of a hook context related to the unit's status. 236 type ContextStatus interface { 237 // UnitStatus returns the executing unit's current status. 238 UnitStatus() (*StatusInfo, error) 239 240 // SetUnitStatus updates the unit's status. 241 SetUnitStatus(StatusInfo) error 242 243 // ApplicationStatus returns the executing unit's application status 244 // (including all units). 245 ApplicationStatus() (ApplicationStatusInfo, error) 246 247 // SetApplicationStatus updates the status for the unit's application. 248 SetApplicationStatus(StatusInfo) error 249 } 250 251 // RebootPriority is the type used for reboot requests. 252 type RebootPriority int 253 254 // ContextInstance is the part of a hook context related to the unit's instance. 255 type ContextInstance interface { 256 // AvailabilityZone returns the executing unit's availability zone or an error 257 // if it was not found (or is not available). 258 AvailabilityZone() (string, error) 259 260 // RequestReboot will set the reboot flag to true on the machine agent 261 RequestReboot(prio RebootPriority) error 262 } 263 264 // ContextNetworking is the part of a hook context related to network 265 // interface of the unit's instance. 266 type ContextNetworking interface { 267 // PublicAddress returns the executing unit's public address or an 268 // error if it is not available. 269 PublicAddress() (string, error) 270 271 // PrivateAddress returns the executing unit's private address or an 272 // error if it is not available. 273 PrivateAddress() (string, error) 274 275 // OpenPortRange marks the supplied port range for opening. 276 OpenPortRange(endpointName string, portRange network.PortRange) error 277 278 // ClosePortRange ensures the supplied port range is closed even when 279 // the executing unit's application is exposed (unless it is opened 280 // separately by a co-located unit). 281 ClosePortRange(endpointName string, portRange network.PortRange) error 282 283 // OpenedPortRanges returns all port ranges currently opened by this 284 // unit on its assigned machine grouped by endpoint name. 285 OpenedPortRanges() network.GroupedPortRanges 286 287 // NetworkInfo returns the network info for the given bindings on the given relation. 288 NetworkInfo(bindingNames []string, relationId int) (map[string]params.NetworkInfoResult, error) 289 } 290 291 // ContextLeadership is the part of a hook context related to the 292 // unit leadership. 293 type ContextLeadership interface { 294 // IsLeader returns true if the local unit is known to be leader for at 295 // least the next 30s. 296 IsLeader() (bool, error) 297 298 // LeaderSettings returns the current leader settings. Once leader settings 299 // have been read in a given context, they will not be updated other than 300 // via successful calls to WriteLeaderSettings. 301 LeaderSettings() (map[string]string, error) 302 303 // WriteLeaderSettings writes the supplied settings directly to state, or 304 // fails if the local unit is not the application's leader. 305 WriteLeaderSettings(map[string]string) error 306 } 307 308 // ContextMetrics is the part of a hook context related to metrics. 309 type ContextMetrics interface { 310 // AddMetric records a metric to return after hook execution. 311 AddMetric(string, string, time.Time) error 312 // AddMetricLabels records a metric with tags to return after hook execution. 313 AddMetricLabels(string, string, time.Time, map[string]string) error 314 } 315 316 // ContextStorage is the part of a hook context related to storage 317 // resources associated with the unit. 318 type ContextStorage interface { 319 // StorageTags returns a list of tags for storage instances 320 // attached to the unit or an error if they are not available. 321 StorageTags() ([]names.StorageTag, error) 322 323 // Storage returns the ContextStorageAttachment with the supplied 324 // tag if it was found, and an error if it was not found or is not 325 // available to the context. 326 Storage(names.StorageTag) (ContextStorageAttachment, error) 327 328 // HookStorage returns the storage attachment associated 329 // the executing hook if it was found, and an error if it 330 // was not found or is not available. 331 HookStorage() (ContextStorageAttachment, error) 332 333 // AddUnitStorage saves storage constraints in the context. 334 AddUnitStorage(map[string]params.StorageConstraints) error 335 } 336 337 // ContextResources exposes the functionality needed by the 338 // "resource-*" hook commands. 339 type ContextResources interface { 340 // DownloadResource downloads the named resource and returns 341 // the path to which it was downloaded. 342 DownloadResource(name string) (filePath string, _ error) 343 } 344 345 // ContextPayloads exposes the functionality needed by the 346 // "payload-*" hook commands. 347 type ContextPayloads interface { 348 // GetPayload returns the payload info corresponding to the given ID. 349 GetPayload(class, id string) (*payloads.Payload, error) 350 // TrackPayload records the payload info in the hook context. 351 TrackPayload(payload payloads.Payload) error 352 // UntrackPayload removes the payload from our list of payloads to track. 353 UntrackPayload(class, id string) error 354 // SetPayloadStatus sets the status of the payload. 355 SetPayloadStatus(class, id, status string) error 356 // ListPayloads returns the list of registered payload IDs. 357 ListPayloads() ([]string, error) 358 // FlushPayloads pushes the hook context data out to state. 359 FlushPayloads() error 360 } 361 362 // ContextRelations exposes the relations associated with the unit. 363 type ContextRelations interface { 364 // Relation returns the relation with the supplied id if it was found, and 365 // an error if it was not found or is not available. 366 Relation(id int) (ContextRelation, error) 367 368 // RelationIds returns the ids of all relations the executing unit is 369 // currently participating in or an error if they are not available. 370 RelationIds() ([]int, error) 371 } 372 373 // ContextRelation expresses the capabilities of a hook with respect to a relation. 374 // 375 //go:generate go run go.uber.org/mock/mockgen -package mocks -destination mocks/context_relation_mock.go github.com/juju/juju/worker/uniter/runner/jujuc ContextRelation 376 type ContextRelation interface { 377 378 // Id returns an integer which uniquely identifies the relation. 379 Id() int 380 381 // Name returns the name the locally executing charm assigned to this relation. 382 Name() string 383 384 // RelationTag returns the relation tag. 385 RelationTag() names.RelationTag 386 387 // FakeId returns a string of the form "relation-name:123", which uniquely 388 // identifies the relation to the hook. In reality, the identification 389 // of the relation is the integer following the colon, but the composed 390 // name is useful to humans observing it. 391 FakeId() string 392 393 // Settings allows read/write access to the local unit's settings in 394 // this relation. 395 Settings() (Settings, error) 396 397 // ApplicationSettings allows read/write access to the application settings in 398 // this relation, but only if the current unit is leader. 399 ApplicationSettings() (Settings, error) 400 401 // UnitNames returns a list of the remote units in the relation. 402 UnitNames() []string 403 404 // ReadSettings returns the settings of any remote unit in the relation. 405 ReadSettings(unit string) (params.Settings, error) 406 407 // ReadApplicationSettings returns the application settings of any remote unit in the relation. 408 ReadApplicationSettings(app string) (params.Settings, error) 409 410 // Suspended returns true if the relation is suspended. 411 Suspended() bool 412 413 // SetStatus sets the relation's status. 414 SetStatus(relation.Status) error 415 416 // RemoteApplicationName returns the application on the other end of 417 // the relation from the perspective of this unit. 418 RemoteApplicationName() string 419 420 // Life returns the relation's current life state. 421 Life() life.Value 422 } 423 424 // ContextStorageAttachment expresses the capabilities of a hook with 425 // respect to a storage attachment. 426 type ContextStorageAttachment interface { 427 428 // Tag returns a tag which uniquely identifies the storage attachment 429 // in the context of the unit. 430 Tag() names.StorageTag 431 432 // Kind returns the kind of the storage. 433 Kind() storage.StorageKind 434 435 // Location returns the location of the storage: the mount point for 436 // filesystem-kind stores, and the device path for block-kind stores. 437 Location() string 438 } 439 440 // ContextVersion expresses the parts of a hook context related to 441 // reporting workload versions. 442 type ContextVersion interface { 443 444 // UnitWorkloadVersion returns the currently set workload version for 445 // the unit. 446 UnitWorkloadVersion() (string, error) 447 448 // SetUnitWorkloadVersion updates the workload version for the unit. 449 SetUnitWorkloadVersion(string) error 450 } 451 452 // Settings is implemented by types that manipulate unit settings. 453 type Settings interface { 454 Map() params.Settings 455 Set(string, string) 456 Delete(string) 457 } 458 459 // NewRelationIdValue returns a gnuflag.Value for convenient parsing of relation 460 // ids in ctx. 461 func NewRelationIdValue(ctx Context, result *int) (*relationIdValue, error) { 462 v := &relationIdValue{result: result, ctx: ctx} 463 id := -1 464 if r, err := ctx.HookRelation(); err == nil { 465 id = r.Id() 466 v.value = r.FakeId() 467 } else if !errors.IsNotFound(err) { 468 return nil, errors.Trace(err) 469 } 470 *result = id 471 return v, nil 472 } 473 474 // relationIdValue implements gnuflag.Value for use in relation commands. 475 type relationIdValue struct { 476 result *int 477 ctx Context 478 value string 479 } 480 481 // String returns the current value. 482 func (v *relationIdValue) String() string { 483 return v.value 484 } 485 486 // Set interprets value as a relation id, if possible, and returns an error 487 // if it is not known to the system. The parsed relation id will be written 488 // to v.result. 489 func (v *relationIdValue) Set(value string) error { 490 trim := value 491 if idx := strings.LastIndex(trim, ":"); idx != -1 { 492 trim = trim[idx+1:] 493 } 494 id, err := strconv.Atoi(trim) 495 if err != nil { 496 return fmt.Errorf("invalid relation id") 497 } 498 if _, err := v.ctx.Relation(id); err != nil { 499 return errors.Trace(err) 500 } 501 *v.result = id 502 v.value = value 503 return nil 504 }