2020-07-09 22:04:51 +00:00
|
|
|
package xds
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2021-02-26 22:23:15 +00:00
|
|
|
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
2021-02-22 21:00:15 +00:00
|
|
|
|
2020-07-09 22:04:51 +00:00
|
|
|
"github.com/hashicorp/go-version"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2020-07-31 20:52:49 +00:00
|
|
|
// minSupportedVersion is the oldest mainline version we support. This should always be
|
|
|
|
// the zero'th point release of the last element of proxysupport.EnvoyVersions.
|
2021-09-22 18:48:50 +00:00
|
|
|
minSupportedVersion = version.Must(version.NewVersion("1.16.0"))
|
2021-02-22 21:00:15 +00:00
|
|
|
|
2021-09-22 18:48:50 +00:00
|
|
|
// add min version constraints for associated feature flags when necessary, for example:
|
|
|
|
// minVersionAllowingEmptyGatewayClustersWithIncrementalXDS = version.Must(version.NewVersion("1.16.0"))
|
2021-04-29 18:54:05 +00:00
|
|
|
|
2021-02-22 21:00:15 +00:00
|
|
|
specificUnsupportedVersions = []unsupportedVersion{}
|
2020-07-09 22:04:51 +00:00
|
|
|
)
|
|
|
|
|
2020-10-06 22:09:13 +00:00
|
|
|
type unsupportedVersion struct {
|
|
|
|
Version *version.Version
|
|
|
|
UpgradeTo string
|
|
|
|
Why string
|
|
|
|
}
|
|
|
|
|
2020-07-09 22:04:51 +00:00
|
|
|
type supportedProxyFeatures struct {
|
2020-07-31 20:52:49 +00:00
|
|
|
// add version dependent feature flags here
|
2021-04-29 18:54:05 +00:00
|
|
|
//
|
2021-09-22 18:48:50 +00:00
|
|
|
// For example, we previously had flags for Envoy < 1.16 called:
|
2021-04-29 18:54:05 +00:00
|
|
|
//
|
2021-09-22 18:48:50 +00:00
|
|
|
// GatewaysNeedStubClusterWhenEmptyWithIncrementalXDS
|
|
|
|
// IncrementalXDSUpdatesMustBeSerial
|
2021-04-29 18:54:05 +00:00
|
|
|
//
|
2021-09-22 18:48:50 +00:00
|
|
|
// Which then manifested in the code for checks with this struct populated.
|
|
|
|
// By dropping support for 1.15, we no longer have any special flags here
|
|
|
|
// but leaving this flagging functionality for future one-offs.
|
2020-07-09 22:04:51 +00:00
|
|
|
}
|
|
|
|
|
2021-02-26 22:23:15 +00:00
|
|
|
func determineSupportedProxyFeatures(node *envoy_core_v3.Node) (supportedProxyFeatures, error) {
|
2020-07-09 22:04:51 +00:00
|
|
|
version := determineEnvoyVersionFromNode(node)
|
2020-07-31 20:52:49 +00:00
|
|
|
return determineSupportedProxyFeaturesFromVersion(version)
|
|
|
|
}
|
|
|
|
|
|
|
|
func determineSupportedProxyFeaturesFromString(vs string) (supportedProxyFeatures, error) {
|
|
|
|
version := version.Must(version.NewVersion(vs))
|
|
|
|
return determineSupportedProxyFeaturesFromVersion(version)
|
|
|
|
}
|
|
|
|
|
|
|
|
func determineSupportedProxyFeaturesFromVersion(version *version.Version) (supportedProxyFeatures, error) {
|
2020-07-09 22:04:51 +00:00
|
|
|
if version == nil {
|
2020-07-31 20:52:49 +00:00
|
|
|
// This would happen on either extremely old builds OR perhaps on
|
|
|
|
// custom builds. Should we error?
|
|
|
|
return supportedProxyFeatures{}, nil
|
2020-07-09 22:04:51 +00:00
|
|
|
}
|
|
|
|
|
2020-07-31 20:52:49 +00:00
|
|
|
if version.LessThan(minSupportedVersion) {
|
|
|
|
return supportedProxyFeatures{}, fmt.Errorf("Envoy %s is too old and is not supported by Consul", version)
|
2020-07-09 22:04:51 +00:00
|
|
|
}
|
2020-07-31 20:52:49 +00:00
|
|
|
|
2020-10-06 22:09:13 +00:00
|
|
|
for _, uv := range specificUnsupportedVersions {
|
|
|
|
if version.Equal(uv.Version) {
|
|
|
|
return supportedProxyFeatures{}, fmt.Errorf(
|
|
|
|
"Envoy %s is too old of a point release and is not supported by Consul because it %s. "+
|
|
|
|
"Please upgrade to version %s.",
|
|
|
|
version,
|
|
|
|
uv.Why,
|
|
|
|
uv.UpgradeTo,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-29 18:54:05 +00:00
|
|
|
sf := supportedProxyFeatures{}
|
|
|
|
|
2021-09-22 18:48:50 +00:00
|
|
|
// add version contraints to poipulate feature flags here when necessary, for example:
|
|
|
|
/*
|
|
|
|
if version.LessThan(minVersionAllowingEmptyGatewayClustersWithIncrementalXDS) {
|
|
|
|
sf.GatewaysNeedStubClusterWhenEmptyWithIncrementalXDS = true
|
|
|
|
}
|
|
|
|
*/
|
2021-04-29 18:54:05 +00:00
|
|
|
|
|
|
|
return sf, nil
|
2020-07-09 22:04:51 +00:00
|
|
|
}
|
|
|
|
|
2021-02-26 22:23:15 +00:00
|
|
|
func determineEnvoyVersionFromNode(node *envoy_core_v3.Node) *version.Version {
|
2020-07-09 22:04:51 +00:00
|
|
|
if node == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if node.UserAgentVersionType == nil {
|
2021-02-22 21:00:15 +00:00
|
|
|
return nil
|
2020-07-09 22:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if node.UserAgentName != "envoy" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-02-26 22:23:15 +00:00
|
|
|
bv, ok := node.UserAgentVersionType.(*envoy_core_v3.Node_UserAgentBuildVersion)
|
2020-07-09 22:04:51 +00:00
|
|
|
if !ok {
|
|
|
|
// NOTE: we could sniff for *envoycore.Node_UserAgentVersion and do more regex but official builds don't have this problem.
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if bv.UserAgentBuildVersion == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
v := bv.UserAgentBuildVersion.Version
|
|
|
|
|
|
|
|
return version.Must(version.NewVersion(
|
|
|
|
fmt.Sprintf("%d.%d.%d",
|
|
|
|
v.GetMajorNumber(),
|
|
|
|
v.GetMinorNumber(),
|
|
|
|
v.GetPatch(),
|
|
|
|
),
|
|
|
|
))
|
|
|
|
}
|