github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/core/assumes/featureset.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package assumes 5 6 import ( 7 chassumes "github.com/juju/charm/v12/assumes" 8 "github.com/juju/collections/set" 9 "github.com/juju/version/v2" 10 ) 11 12 // Feature identifies a particular piece of functionality provided by a Juju 13 // controller depending on the substrate associated with a particular model. 14 type Feature struct { 15 // The name of the feature. 16 Name string 17 18 // A user-friendly description of what the feature provides. 19 Description string 20 21 // An optional semantic version for this feature. It can be left empty 22 // to signify that a particular feature is available without explicitly 23 // specifying a version 24 Version *version.Number 25 } 26 27 // FeatureSet describes a set of features supported by a particular model. 28 type FeatureSet struct { 29 features map[string]Feature 30 } 31 32 // Merge the features from other into this feature set. 33 func (fs *FeatureSet) Merge(other FeatureSet) { 34 for _, feat := range other.features { 35 fs.Add(feat) 36 } 37 } 38 39 // AsList returns the contents of this set as a list sorted by feature name. 40 func (fs *FeatureSet) AsList() []Feature { 41 set := set.NewStrings() 42 for featName := range fs.features { 43 set.Add(featName) 44 } 45 46 var list []Feature 47 for _, featName := range set.SortedValues() { 48 list = append(list, fs.features[featName]) 49 } 50 51 return list 52 } 53 54 // Add a list of Features to the feature set. Duplicate feature entries 55 // will be ignored. 56 func (fs *FeatureSet) Add(features ...Feature) { 57 if fs.features == nil { 58 fs.features = make(map[string]Feature) 59 } 60 61 for _, feat := range features { 62 fs.features[feat.Name] = feat 63 } 64 } 65 66 // Get a feature with the provide feature name. The method returns a boolean 67 // value to indicate if the feature was found. 68 func (fs FeatureSet) Get(featName string) (Feature, bool) { 69 if fs.features == nil { 70 return Feature{}, false 71 } 72 73 feat, found := fs.features[featName] 74 return feat, found 75 } 76 77 // Satisfies checks whether the feature set contents satisfy the provided 78 // "assumes" expression tree and returns an error otherwise. 79 func (fs FeatureSet) Satisfies(assumesExprTree *chassumes.ExpressionTree) error { 80 if assumesExprTree == nil || assumesExprTree.Expression == nil { 81 return nil // empty expressions are implicitly satisfied 82 } 83 84 return satisfyExpr(fs, assumesExprTree.Expression, 0) 85 }