get.porter.sh/porter@v1.3.0/pkg/schema/check-strategy.go (about) 1 package schema 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/Masterminds/semver/v3" 8 ) 9 10 // CheckStrategy is an enum of values for handling schemaVersion 11 // comparisons of two resources. Allowed values are: CheckStrategyExact, 12 // CheckStrategyMinor, CheckStrategyMajor, CheckStrategyNone. 13 type CheckStrategy string 14 15 const ( 16 // CheckStrategyExact requires that resource schemaVersion values exactly match the supported schema version. 17 CheckStrategyExact CheckStrategy = "exact" 18 19 // CheckStrategyMinor requires that resource schemaVersion values match the MAJOR.MINOR portion of the supported schema version. 20 CheckStrategyMinor CheckStrategy = "minor" 21 22 // CheckStrategyMajor requires that resource schemaVersion values exactly match the MAJOR portion of the supported schema version. 23 CheckStrategyMajor CheckStrategy = "major" 24 25 // CheckStrategyNone ignores the resource schemaVersion. Errors will most likely ensue but have fun! 26 CheckStrategyNone CheckStrategy = "none" 27 ) 28 29 // ErrInvalidSchemaVersion is used when the schemaVersion of two resources do not match exactly. 30 var ErrInvalidSchemaVersion = errors.New("invalid schema version") 31 32 // ValidateSchemaVersion checks the specified schema version against the supported version, 33 // returning if the result is a warning only. Warnings are returned when the versions are not an exact match. 34 // A warning is not returned when CheckStrategyNone is used. 35 func ValidateSchemaVersion(strategy CheckStrategy, supported *semver.Constraints, specified string, defaultVersion *semver.Version) (bool, error) { 36 if specified == "" { 37 specified = "(none)" 38 } 39 baseMessage := fmt.Errorf("the schema version is %s but the supported schema version is %s. See https://porter.sh/reference/file-formats/#supported-versions for more details: %w", 40 specified, supported, ErrInvalidSchemaVersion) 41 42 specifiedV, err := semver.NewVersion(specified) 43 if err != nil { 44 isWarning := strategy == CheckStrategyNone 45 return isWarning, fmt.Errorf("%s is not a valid semantic version: %w", specified, ErrInvalidSchemaVersion) 46 } 47 48 isSchemaVersionSatisfied := supported.Check(specifiedV) 49 switch strategy { 50 case CheckStrategyNone: 51 // this strategy always passes 52 case CheckStrategyExact: 53 // Check if the schema version satisfies the supported version range 54 if isSchemaVersionSatisfied { 55 return false, nil 56 } else { 57 return false, baseMessage 58 } 59 case CheckStrategyMinor: 60 // Check if the schema version matches the MAJOR.MINOR version number of the currently supported (default) schema version 61 supportedMinor, _ := semver.NewConstraint(fmt.Sprintf("~%d.%d.0-0", defaultVersion.Major(), defaultVersion.Minor())) 62 isMinorMatch := supportedMinor.Check(specifiedV) 63 if !isMinorMatch { 64 return false, fmt.Errorf("the schema version MAJOR.MINOR values do not match: %w", baseMessage) 65 } 66 case CheckStrategyMajor: 67 // Check if the schema version matches the MAJOR version number of the currently supported (default) schema version 68 supportedMajor, _ := semver.NewConstraint(fmt.Sprintf("^%d.0.0-0", defaultVersion.Major())) 69 isMajorMatch := supportedMajor.Check(specifiedV) 70 if !isMajorMatch { 71 return false, fmt.Errorf("the schema version MAJOR values do not match: %w", baseMessage) 72 } 73 default: 74 return false, fmt.Errorf("unknown schema.CheckStrategy %v", strategy) 75 } 76 77 if isSchemaVersionSatisfied { 78 return false, nil 79 } else { 80 // Even if the check passed, print a warning if it wasn't strictly supported 81 return true, fmt.Errorf("WARNING: %w", baseMessage) 82 } 83 }