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  }