// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package xdscommon
import (
_ "embed"
"fmt"
"slices"
"strconv"
"strings"
)
// File containing the canonical range of supported Envoy versions for this version of Consul.
// This file should contain exactly one point release for each major release of Envoy, per line.
// All other contents must be blank lines or comments. Comments must be on their own line starting with '#'.
//
//go:embed ENVOY_VERSIONS
var envoyVersionsRaw string
// initEnvoyVersions calls parseEnvoyVersions and panics if it returns an error. Used to set EnvoyVersions.
func initEnvoyVersions ( ) [ ] string {
versions , err := parseEnvoyVersions ( envoyVersionsRaw )
if err != nil {
panic ( err )
}
return versions
}
// parseEnvoyVersions parses the ENVOY_VERSIONS file and returns a list of supported Envoy versions.
func parseEnvoyVersions ( raw string ) ( [ ] string , error ) {
lines := strings . Split ( raw , "\n" )
var versionLines [ ] string
for _ , line := range lines {
trimmed := strings . TrimSpace ( line )
if trimmed == "" || strings . HasPrefix ( trimmed , "#" ) {
continue // skip empty lines and comments
}
// Assume all remaining lines are valid Envoy versions in the format "X.Y.Z".
versionParts := strings . Split ( trimmed , "." )
if len ( versionParts ) != 3 {
return nil , fmt . Errorf ( "invalid version in ENVOY_VERSIONS: %s" , line )
}
for _ , v := range versionParts {
if _ , err := strconv . Atoi ( v ) ; err != nil {
return nil , fmt . Errorf ( "invalid version in ENVOY_VERSIONS: %s" , line )
}
}
versionLines = append ( versionLines , trimmed )
}
// Ensure sorted in descending order.
// We do this here as well as tests because other code (e.g. Makefile) may depend on the order
// of these values, so we want early detection in case tests are not run before compilation.
if ! slices . IsSortedFunc ( versionLines , func ( v1 , v2 string ) int {
return strings . Compare ( v2 , v1 )
} ) {
return nil , fmt . Errorf ( "ENVOY_VERSIONS must be sorted in descending order" )
}
return versionLines , nil
}
// EnvoyVersions lists the latest officially supported versions of envoy.
//
// This list must be sorted by semver descending. Only one point release for
// each major release should be present.
//
// see: https://www.consul.io/docs/connect/proxies/envoy#supported-versions
var EnvoyVersions = initEnvoyVersions ( )
// UnsupportedEnvoyVersions lists any unsupported Envoy versions (mainly minor versions) that fall
// within the range of EnvoyVersions above.
// For example, if patch 1.21.3 (patch 3) had a breaking change, and was not supported
// even though 1.21 is a supported major release, you would then add 1.21.3 to this list.
// This list will be empty in most cases.
//
// see: https://www.consul.io/docs/connect/proxies/envoy#supported-versions
var UnsupportedEnvoyVersions = [ ] string { }
// GetMaxEnvoyMajorVersion grabs the first value in EnvoyVersions and strips the last number off in order
// to return the maximum supported Envoy "major" version.
// For example, if the input string is "1.14.1", the function would return "1.14".
func GetMaxEnvoyMajorVersion ( ) string {
s := strings . Split ( getMaxEnvoyVersion ( ) , "." )
return s [ 0 ] + "." + s [ 1 ]
}
// GetMinEnvoyMajorVersion grabs the last value in EnvoyVersions and strips the patch number off in order
// to return the minimum supported Envoy "major" version.
// For example, if the input string is "1.12.1", the function would return "1.12".
func GetMinEnvoyMajorVersion ( ) string {
s := strings . Split ( getMinEnvoyVersion ( ) , "." )
return s [ 0 ] + "." + s [ 1 ]
}
// getMaxEnvoyVersion returns the first (highest) value in EnvoyVersions.
func getMaxEnvoyVersion ( ) string {
return EnvoyVersions [ 0 ]
}
// getMinEnvoyVersion returns the last (lowest) value in EnvoyVersions.
func getMinEnvoyVersion ( ) string {
return EnvoyVersions [ len ( EnvoyVersions ) - 1 ]
}