github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/core/assumes/sat_checker_test.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  	"strings"
     8  
     9  	chassumes "github.com/juju/charm/v12/assumes"
    10  	"github.com/juju/testing"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/version/v2"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/yaml.v3"
    15  )
    16  
    17  type SatCheckerSuite struct {
    18  	testing.IsolationSuite
    19  }
    20  
    21  var _ = gc.Suite(&SatCheckerSuite{})
    22  
    23  func (s *SatCheckerSuite) TestErrorReportingForSimpleExpression(c *gc.C) {
    24  	fs := genFeatureSet(c)
    25  
    26  	exprTree := mustParseAssumesExpr(c, `
    27  assumes:
    28    - storage >= 2.19.43
    29    - storage < 2.20
    30  `)
    31  
    32  	expErr := `
    33  Charm feature requirements cannot be met:
    34    - charm requires feature "storage" (version >= 2.19.43) but model currently supports version 2.19.42
    35  
    36  Feature descriptions:
    37    - "storage": create and manipulate storage primitives
    38  
    39  For additional information please see: https://juju.is/docs/olm/supported-features`[1:]
    40  
    41  	err := fs.Satisfies(exprTree)
    42  	c.Assert(err, jc.Satisfies, IsRequirementsNotSatisfiedError, gc.Commentf("expected to get a RequirementsNotSatisfied error"))
    43  	c.Assert(err.Error(), gc.Equals, expErr)
    44  }
    45  
    46  func (s *SatCheckerSuite) TestErrorReportingForCompositeExpressions(c *gc.C) {
    47  	fs := genFeatureSet(c)
    48  
    49  	exprTree := mustParseAssumesExpr(c, `
    50  assumes:
    51    - any-of:
    52      - k8s-api >= 42
    53      - random-feature-a
    54    - all-of:
    55      - block-storage
    56      - juju >= 3
    57  `)
    58  
    59  	expErr := `
    60  Charm feature requirements cannot be met:
    61    - charm requires at least one of the following:
    62      - charm requires feature "k8s-api" (version >= 42.0.0) but model currently supports version 1.18.0
    63      - charm requires feature "random-feature-a" but model does not support it
    64    - charm requires all of the following:
    65      - charm requires feature "block-storage" but model does not support it
    66      - charm requires feature "juju" (version >= 3.0.0) but model currently supports version 2.19.42
    67  
    68  Feature descriptions:
    69    - "juju": version of Juju running on the controller
    70    - "k8s-api": access to the kubernetes API
    71  
    72  For additional information please see: https://juju.is/docs/olm/supported-features`[1:]
    73  
    74  	err := fs.Satisfies(exprTree)
    75  	c.Assert(err, jc.Satisfies, IsRequirementsNotSatisfiedError, gc.Commentf("expected to get a RequirementsNotSatisfied error"))
    76  	c.Assert(err.Error(), gc.Equals, expErr)
    77  }
    78  
    79  func (s *SatCheckerSuite) TestErrorReportingForMultiLevelExpressionTree(c *gc.C) {
    80  	fs := genFeatureSet(c)
    81  
    82  	exprTree := mustParseAssumesExpr(c, `
    83  assumes:
    84    - storage >= 42
    85    - storage < 45
    86    - any-of:
    87      - k8s-api >= 1.17
    88      - random-feature-a
    89    - all-of:
    90      - k8s-api >= 1.17
    91      - juju >= 3
    92      - any-of:
    93        - random-feature-b
    94        - random-feature-c
    95    - any-of:
    96      - random-feature-d
    97      - random-feature-e
    98  `)
    99  
   100  	expErr := `
   101  Charm feature requirements cannot be met:
   102    - charm requires feature "storage" (version >= 42.0.0) but model currently supports version 2.19.42
   103    - charm requires all of the following:
   104      - charm requires feature "juju" (version >= 3.0.0) but model currently supports version 2.19.42
   105      - charm requires at least one of the following:
   106        - charm requires feature "random-feature-b" but model does not support it
   107        - charm requires feature "random-feature-c" but model does not support it
   108    - charm requires at least one of the following:
   109      - charm requires feature "random-feature-d" but model does not support it
   110      - charm requires feature "random-feature-e" but model does not support it
   111  
   112  Feature descriptions:
   113    - "juju": version of Juju running on the controller
   114    - "storage": create and manipulate storage primitives
   115  
   116  For additional information please see: https://juju.is/docs/olm/supported-features`[1:]
   117  
   118  	err := fs.Satisfies(exprTree)
   119  	c.Assert(err, jc.Satisfies, IsRequirementsNotSatisfiedError, gc.Commentf("expected to get a RequirementsNotSatisfied error"))
   120  	c.Assert(err.Error(), gc.Equals, expErr)
   121  }
   122  
   123  func (s *SatCheckerSuite) TestAssumesExpressionSatisfied(c *gc.C) {
   124  	fs := genFeatureSet(c)
   125  
   126  	exprTree := mustParseAssumesExpr(c, `
   127  assumes:
   128    - storage >= 2
   129    - storage < 3
   130    - any-of:
   131      - k8s-api >= 1.17
   132      - load-balancer
   133    - all-of:
   134      - juju >= 2
   135      - juju < 3
   136      - storage
   137  `)
   138  
   139  	err := fs.Satisfies(exprTree)
   140  	c.Assert(err, jc.ErrorIsNil, gc.Commentf("expected assumes expression tree to be satisfied"))
   141  }
   142  
   143  func genFeatureSet(c *gc.C) FeatureSet {
   144  	var fs FeatureSet
   145  	fs.Add(
   146  		Feature{
   147  			Name:        "k8s-api",
   148  			Description: "access to the kubernetes API",
   149  			Version:     mustParseVersion(c, "1.18"),
   150  		},
   151  		Feature{
   152  			Name:        "juju",
   153  			Description: "version of Juju running on the controller",
   154  			Version:     mustParseVersion(c, "2.19.42"),
   155  		},
   156  		Feature{
   157  			Name:        "storage",
   158  			Description: "create and manipulate storage primitives",
   159  			Version:     mustParseVersion(c, "2.19.42"),
   160  		},
   161  		Feature{
   162  			Name:        "load-balancer",
   163  			Description: "create and manipulate load-balancers",
   164  		},
   165  	)
   166  
   167  	return fs
   168  }
   169  
   170  func mustParseVersion(c *gc.C, verStr string) *version.Number {
   171  	ver, err := version.ParseNonStrict(verStr)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	return &ver
   174  }
   175  
   176  func mustParseAssumesExpr(c *gc.C, exprYAML string) *chassumes.ExpressionTree {
   177  	var payload = struct {
   178  		ExprTree chassumes.ExpressionTree `yaml:"assumes"`
   179  	}{}
   180  
   181  	err := yaml.NewDecoder(strings.NewReader(exprYAML)).Decode(&payload)
   182  	c.Assert(err, jc.ErrorIsNil)
   183  
   184  	return &payload.ExprTree
   185  }