github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/lease/secretaries.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package lease 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/names/v5" 11 12 "github.com/juju/juju/api/agent/agent" 13 "github.com/juju/juju/core/lease" 14 ) 15 16 // SingularSecretary implements Secretary to restrict claims to either 17 // a lease for the controller or the specific model it's asking for, 18 // holdable only by machine-tag strings. 19 type SingularSecretary struct { 20 ControllerUUID string 21 } 22 23 // CheckLease is part of the lease.Secretary interface. 24 func (s SingularSecretary) CheckLease(key lease.Key) error { 25 if key.Lease != s.ControllerUUID && key.Lease != key.ModelUUID { 26 return errors.New("expected controller or model UUID") 27 } 28 return nil 29 } 30 31 // CheckHolder is part of the lease.Secretary interface. 32 func (s SingularSecretary) CheckHolder(name string) error { 33 tag, err := names.ParseTag(name) 34 if err != nil { 35 return errors.Annotate(err, "expected a valid tag") 36 } 37 if !agent.IsAllowedControllerTag(tag.Kind()) { 38 return errors.New("expected machine or controller tag") 39 } 40 return nil 41 } 42 43 // CheckDuration is part of the lease.Secretary interface. 44 func (s SingularSecretary) CheckDuration(duration time.Duration) error { 45 if duration <= 0 { 46 return errors.NewNotValid(nil, "non-positive") 47 } 48 return nil 49 } 50 51 // LeadershipSecretary implements Secretary; it checks that leases are 52 // application names, and holders are unit names. 53 type LeadershipSecretary struct{} 54 55 // CheckLease is part of the lease.Secretary interface. 56 func (LeadershipSecretary) CheckLease(key lease.Key) error { 57 if !names.IsValidApplication(key.Lease) { 58 return errors.NewNotValid(nil, "not an application name") 59 } 60 return nil 61 } 62 63 // CheckHolder is part of the lease.Secretary interface. 64 func (LeadershipSecretary) CheckHolder(name string) error { 65 if !names.IsValidUnit(name) { 66 return errors.NewNotValid(nil, "not a unit name") 67 } 68 return nil 69 } 70 71 // CheckDuration is part of the lease.Secretary interface. 72 func (LeadershipSecretary) CheckDuration(duration time.Duration) error { 73 if duration <= 0 { 74 return errors.NewNotValid(nil, "non-positive") 75 } 76 return nil 77 } 78 79 // SecretaryFinder returns a function to find the correct secretary to 80 // use for validation for a specific lease namespace (or an error if 81 // the namespace isn't valid). 82 func SecretaryFinder(controllerUUID string) func(string) (Secretary, error) { 83 secretaries := map[string]Secretary{ 84 lease.ApplicationLeadershipNamespace: LeadershipSecretary{}, 85 lease.SingularControllerNamespace: SingularSecretary{ 86 ControllerUUID: controllerUUID, 87 }, 88 } 89 return func(namespace string) (Secretary, error) { 90 result, found := secretaries[namespace] 91 if !found { 92 return nil, errors.NotValidf("namespace %q", namespace) 93 } 94 return result, nil 95 } 96 }