pkg/eniconfig/eniconfig.go (90 lines of code) (raw):
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
// Package eniconfig handles eniconfig CRD
package eniconfig
import (
"context"
"os"
"k8s.io/apimachinery/pkg/types"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/aws/amazon-vpc-cni-k8s/pkg/apis/crd/v1alpha1"
"github.com/aws/amazon-vpc-cni-k8s/pkg/k8sapi"
"github.com/aws/amazon-vpc-cni-k8s/pkg/utils/logger"
)
const (
defaultEniConfigAnnotationDef = "k8s.amazonaws.com/eniConfig"
defaultEniConfigLabelDef = "k8s.amazonaws.com/eniConfig"
EniConfigDefault = "default"
// when this is defined, it is to be treated as the source of truth for the eniconfig.
// it is meant to be used for out-of-band mananagement of the eniConfig - i.e. on the kubelet or elsewhere
externalEniConfigLabel = "vpc.amazonaws.com/externalEniConfig"
// when "ENI_CONFIG_LABEL_DEF is defined, ENIConfigController will use that label key to
// search if is setting value for eniConfigLabelDef
// Example:
// Node has set label k8s.amazonaws.com/eniConfigCustom=customConfig
// We can get that value in controller by setting environmental variable ENI_CONFIG_LABEL_DEF
// ENI_CONFIG_LABEL_DEF=k8s.amazonaws.com/eniConfigOverride
// This will set eniConfigLabelDef to eniConfigOverride
envEniConfigAnnotationDef = "ENI_CONFIG_ANNOTATION_DEF"
envEniConfigLabelDef = "ENI_CONFIG_LABEL_DEF"
)
// ENIConfig interface
type ENIConfig interface {
MyENIConfig(client.Client) (*v1alpha1.ENIConfigSpec, error)
GetENIConfigName(context.Context, client.Client) (string, error)
}
// ErrNoENIConfig is the missing ENIConfig error
var ErrNoENIConfig = errors.New("eniconfig: eniconfig is not available")
var log = logger.Get()
// ENIConfigInfo returns locally cached ENIConfigs
type ENIConfigInfo struct {
ENI map[string]v1alpha1.ENIConfigSpec
MyENI string
EniConfigAnnotationDef string
EniConfigLabelDef string
}
// MyENIConfig returns the ENIConfig applicable to the particular node
func MyENIConfig(ctx context.Context, k8sClient client.Client) (*v1alpha1.ENIConfigSpec, error) {
node, err := k8sapi.GetNode(ctx, k8sClient)
if err != nil {
log.Debugf("Error while retrieving Node")
}
eniConfigName, err := GetNodeSpecificENIConfigName(node)
if err != nil {
log.Debugf("Error while retrieving Node ENIConfig name")
}
log.Infof("Found ENI Config Name: %s", eniConfigName)
var eniConfig v1alpha1.ENIConfig
err = k8sClient.Get(ctx, types.NamespacedName{Name: eniConfigName}, &eniConfig)
if err != nil {
log.Errorf("error while retrieving eniconfig: %s", err)
return nil, ErrNoENIConfig
}
return &v1alpha1.ENIConfigSpec{
SecurityGroups: eniConfig.Spec.SecurityGroups,
Subnet: eniConfig.Spec.Subnet,
}, nil
}
// getEniConfigAnnotationDef returns eniConfigAnnotation
func getEniConfigAnnotationDef() string {
inputStr, found := os.LookupEnv(envEniConfigAnnotationDef)
if !found {
return defaultEniConfigAnnotationDef
}
if len(inputStr) > 0 {
log.Debugf("Using ENI_CONFIG_ANNOTATION_DEF %v", inputStr)
return inputStr
}
return defaultEniConfigAnnotationDef
}
// getEniConfigLabelDef returns eniConfigLabel name
func getEniConfigLabelDef() string {
inputStr, found := os.LookupEnv(envEniConfigLabelDef)
if !found {
return defaultEniConfigLabelDef
}
if len(inputStr) > 0 {
log.Debugf("Using ENI_CONFIG_LABEL_DEF %v", inputStr)
return inputStr
}
return defaultEniConfigLabelDef
}
func GetNodeSpecificENIConfigName(node corev1.Node) (string, error) {
var eniConfigName string
//Derive ENIConfig Name from either externally managed label, Node Annotations or Labels
labels := node.GetLabels()
eniConfigName, ok := labels[externalEniConfigLabel]
if !ok {
eniConfigName, ok = node.GetAnnotations()[getEniConfigAnnotationDef()]
if !ok {
eniConfigName, ok = node.GetLabels()[getEniConfigLabelDef()]
if !ok {
eniConfigName = EniConfigDefault
}
}
}
return eniConfigName, nil
}