pkg/inject/virtualgateway_envoy.go (186 lines of code) (raw):
package inject
import (
"fmt"
"strconv"
"strings"
appmesh "github.com/aws/aws-app-mesh-controller-for-k8s/apis/appmesh/v1beta2"
"github.com/aws/aws-sdk-go/aws"
corev1 "k8s.io/api/core/v1"
)
type virtualGatwayEnvoyConfig struct {
accountID string
awsRegion string
preview bool
enableSDS bool
sdsUdsPath string
logLevel string
adminAccessPort int32
adminAccessLogFile string
sidecarImageRepository string
sidecarImageTag string
readinessProbeInitialDelay int32
readinessProbePeriod int32
enableXrayTracing bool
xrayDaemonPort int32
xraySamplingRate string
enableJaegerTracing bool
jaegerPort string
jaegerAddress string
enableDatadogTracing bool
datadogTracerPort int32
datadogTracerAddress string
enableStatsTags bool
enableStatsD bool
statsDPort int32
statsDAddress string
statsDSocketPath string
controllerVersion string
k8sVersion string
useDualStackEndpoint bool
enableAdminAccessIPv6 bool
useFipsEndpoint bool
awsAccessKeyId string
awsSecretAccessKey string
awsSessionToken string
}
// newVirtualGatewayEnvoyConfig constructs new newVirtualGatewayEnvoyConfig
func newVirtualGatewayEnvoyConfig(mutatorConfig virtualGatwayEnvoyConfig, ms *appmesh.Mesh, vg *appmesh.VirtualGateway) *virtualGatewayEnvoyConfig {
return &virtualGatewayEnvoyConfig{
ms: ms,
mutatorConfig: mutatorConfig,
vg: vg,
}
}
var _ PodMutator = &virtualGatewayEnvoyConfig{}
// mutator adding a virtualgateway config to envoy pod
type virtualGatewayEnvoyConfig struct {
vg *appmesh.VirtualGateway
ms *appmesh.Mesh
mutatorConfig virtualGatwayEnvoyConfig
}
func (m *virtualGatewayEnvoyConfig) mutate(pod *corev1.Pod) error {
ok, envoyIdx := containsEnvoyContainer(pod)
if !ok {
return nil
}
variables := m.buildTemplateVariables(pod)
envoy := pod.Spec.Containers[envoyIdx]
vg := fmt.Sprintf("mesh/%s/virtualGateway/%s", variables.MeshName, variables.VirtualGatewayOrNodeName)
envMap := map[string]string{}
if err := updateEnvMapForEnvoy(variables, envMap, vg); err != nil {
return err
}
//we override the image to latest Envoy so customers do not have to manually manage
// envoy versions and let controller handle consistency versions across the mesh
if m.virtualGatewayImageOverride(pod) {
envoy.Image = fmt.Sprintf("%s:%s", m.mutatorConfig.sidecarImageRepository, m.mutatorConfig.sidecarImageTag)
}
for idx, env := range pod.Spec.Containers[envoyIdx].Env {
if val, ok := envMap[env.Name]; ok {
if val != env.Value {
envoy.Env[idx].Value = val
}
delete(envMap, env.Name)
}
}
env := getEnvoyEnv(envMap)
envoy.Env = append(envoy.Env, env...)
// customer can bring their own envoy image/spec for virtual gateway so we will only set readiness probe if not already set
if envoy.ReadinessProbe == nil {
envoy.ReadinessProbe = envoyReadinessProbe(m.mutatorConfig.readinessProbeInitialDelay,
m.mutatorConfig.readinessProbePeriod, strconv.Itoa(int(m.mutatorConfig.adminAccessPort)))
}
if m.mutatorConfig.enableSDS && !isSDSDisabled(pod) {
mutateSDSMounts(pod, &envoy, m.mutatorConfig.sdsUdsPath)
}
pod.Spec.Containers[envoyIdx] = envoy
return nil
}
func (m *virtualGatewayEnvoyConfig) buildTemplateVariables(pod *corev1.Pod) EnvoyTemplateVariables {
meshName := m.getAugmentedMeshName()
virtualGatewayName := aws.StringValue(m.vg.Spec.AWSName)
preview := m.getPreview(pod)
useDualStackEndpoint := m.getUseDualStackEndpoint(m.mutatorConfig.useDualStackEndpoint)
sdsEnabled := m.mutatorConfig.enableSDS
useFipsEndpoint := m.getUseFipsEndpoint(m.mutatorConfig.useFipsEndpoint)
if m.mutatorConfig.enableSDS && isSDSDisabled(pod) {
sdsEnabled = false
}
return EnvoyTemplateVariables{
AWSRegion: m.mutatorConfig.awsRegion,
MeshName: meshName,
VirtualGatewayOrNodeName: virtualGatewayName,
Preview: preview,
EnableSDS: sdsEnabled,
SdsUdsPath: m.mutatorConfig.sdsUdsPath,
LogLevel: m.mutatorConfig.logLevel,
AdminAccessPort: m.mutatorConfig.adminAccessPort,
AdminAccessLogFile: m.mutatorConfig.adminAccessLogFile,
EnableXrayTracing: m.mutatorConfig.enableXrayTracing,
XrayDaemonPort: m.mutatorConfig.xrayDaemonPort,
XraySamplingRate: m.mutatorConfig.xraySamplingRate,
EnableJaegerTracing: m.mutatorConfig.enableJaegerTracing,
JaegerPort: m.mutatorConfig.jaegerPort,
JaegerAddress: m.mutatorConfig.jaegerAddress,
EnableDatadogTracing: m.mutatorConfig.enableDatadogTracing,
DatadogTracerPort: m.mutatorConfig.datadogTracerPort,
DatadogTracerAddress: m.mutatorConfig.datadogTracerAddress,
EnableStatsTags: m.mutatorConfig.enableStatsTags,
EnableStatsD: m.mutatorConfig.enableStatsD,
StatsDPort: m.mutatorConfig.statsDPort,
StatsDAddress: m.mutatorConfig.statsDAddress,
StatsDSocketPath: m.mutatorConfig.statsDSocketPath,
ControllerVersion: m.mutatorConfig.controllerVersion,
K8sVersion: m.mutatorConfig.k8sVersion,
UseDualStackEndpoint: useDualStackEndpoint,
EnableAdminAccessForIpv6: m.mutatorConfig.enableAdminAccessIPv6,
UseFipsEndpoint: useFipsEndpoint,
AwsAccessKeyId: m.mutatorConfig.awsAccessKeyId,
AwsSecretAccessKey: m.mutatorConfig.awsSecretAccessKey,
AwsSessionToken: m.mutatorConfig.awsSessionToken,
}
}
func (m *virtualGatewayEnvoyConfig) getPreview(pod *corev1.Pod) string {
preview := m.mutatorConfig.preview
if v, ok := pod.ObjectMeta.Annotations[AppMeshPreviewAnnotation]; ok {
preview = strings.ToLower(v) == "enabled"
}
if preview {
return "1"
}
return "0"
}
func (m *virtualGatewayEnvoyConfig) getAugmentedMeshName() string {
meshName := aws.StringValue(m.ms.Spec.AWSName)
if m.ms.Spec.MeshOwner != nil && aws.StringValue(m.ms.Spec.MeshOwner) != m.mutatorConfig.accountID {
return fmt.Sprintf("%v@%v", meshName, aws.StringValue(m.ms.Spec.MeshOwner))
}
return meshName
}
const (
// when enabled, a virtual gateway image will not be overriden
gatewayImageSkipOverrideModeEnabled = "enabled"
// when disabled, a virtual gateway image will be overriden. This is also the default behavior
gatewayImageSkipOverrideModeDisabled = "disabled"
)
func (m *virtualGatewayEnvoyConfig) virtualGatewayImageOverride(pod *corev1.Pod) bool {
var imageOverrideAnnotation string
if v, ok := pod.ObjectMeta.Annotations[AppMeshGatewaySkipImageOverride]; ok {
imageOverrideAnnotation = v
}
switch strings.ToLower(imageOverrideAnnotation) {
case gatewayImageSkipOverrideModeEnabled:
return false
case gatewayImageSkipOverrideModeDisabled:
return true
default:
return true
}
}
func (m *virtualGatewayEnvoyConfig) getUseDualStackEndpoint(useDualStackEndpoint bool) string {
if useDualStackEndpoint {
return "1"
} else {
return "0"
}
}
func (m *virtualGatewayEnvoyConfig) getUseFipsEndpoint(useFipsEndpoint bool) string {
if useFipsEndpoint {
return "1"
} else {
return "0"
}
}