-
Notifications
You must be signed in to change notification settings - Fork 728
/
eniconfig.go
151 lines (127 loc) · 4.75 KB
/
eniconfig.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 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/utils/logger"
)
const (
defaultEniConfigAnnotationDef = "k8s.amazonaws.com/eniConfig"
defaultEniConfigLabelDef = "k8s.amazonaws.com/eniConfig"
eniConfigDefault = "default"
eniConfigLabel = "vpc.amazonaws.com/eniConfig"
// 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) {
eniConfigName, err := GetNodeSpecificENIConfigName(ctx, k8sClient)
if err != nil {
log.Debugf("Error while retrieving Node 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(ctx context.Context, k8sClient client.Client) (string, error) {
var eniConfigName string
log.Infof("Get Node Info for: %s", os.Getenv("MY_NODE_NAME"))
var node corev1.Node
err := k8sClient.Get(ctx, types.NamespacedName{Name: os.Getenv("MY_NODE_NAME")}, &node)
if err != nil {
log.Errorf("error retrieving node: %s", err)
return eniConfigName, err
}
//Derive ENIConfig Name from either externally managed label, Node Annotations or Labels
val, ok := node.GetLabels()[externalEniConfigLabel]
if !ok {
val, ok = node.GetAnnotations()[getEniConfigAnnotationDef()]
if !ok {
val, ok = node.GetLabels()[getEniConfigLabelDef()]
if !ok {
val = eniConfigDefault
}
}
}
eniConfigName = val
if val != eniConfigDefault {
labels := node.GetLabels()
labels["vpc.amazonaws.com/eniConfig"] = eniConfigName
node.SetLabels(labels)
}
return eniConfigName, nil
}