// 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 }