2018-04-20 18:30:12 +01:00
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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 k8sclient
import (
2020-10-23 10:54:20 -04:00
"context"
2018-04-20 18:30:12 +01:00
"encoding/json"
"fmt"
2019-08-16 18:55:12 +09:00
"net"
2018-07-19 09:02:49 -05:00
"os"
2018-05-03 16:36:49 -04:00
"regexp"
2018-05-09 11:47:37 +01:00
"strings"
2020-04-22 13:51:42 -04:00
"time"
2018-04-20 18:30:12 +01:00
2018-07-30 11:59:13 +01:00
v1 "k8s.io/api/core/v1"
2018-04-20 18:30:12 +01:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2020-03-04 16:42:29 +09:00
"k8s.io/apimachinery/pkg/runtime"
2018-04-20 18:30:12 +01:00
"k8s.io/client-go/kubernetes"
2020-03-04 16:42:29 +09:00
"k8s.io/client-go/kubernetes/scheme"
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
2018-07-19 09:02:49 -05:00
"k8s.io/client-go/rest"
2018-04-20 18:30:12 +01:00
"k8s.io/client-go/tools/clientcmd"
2020-03-04 16:42:29 +09:00
"k8s.io/client-go/tools/record"
"k8s.io/klog"
2018-04-20 18:30:12 +01:00
2018-04-27 19:43:20 +01:00
"github.com/containernetworking/cni/libcni"
2018-04-20 18:30:12 +01:00
"github.com/containernetworking/cni/pkg/skel"
cnitypes "github.com/containernetworking/cni/pkg/types"
2019-10-28 13:04:06 +09:00
nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
2019-12-04 18:21:06 +09:00
netclient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1"
2019-12-05 15:43:27 +09:00
netutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils"
2021-03-16 16:08:53 +09:00
"gopkg.in/k8snetworkplumbingwg/multus-cni.v3/pkg/kubeletclient"
"gopkg.in/k8snetworkplumbingwg/multus-cni.v3/pkg/logging"
"gopkg.in/k8snetworkplumbingwg/multus-cni.v3/pkg/types"
2018-04-20 18:30:12 +01:00
)
2018-09-10 16:27:07 +01:00
const (
2019-01-25 17:49:16 +09:00
resourceNameAnnot = "k8s.v1.cni.cncf.io/resourceName"
defaultNetAnnot = "v1.multus-cni.io/default-network"
networkAttachmentAnnot = "k8s.v1.cni.cncf.io/networks"
2018-09-10 16:27:07 +01:00
)
2018-04-20 18:30:12 +01:00
// NoK8sNetworkError indicates error, no network in kubernetes
2018-04-23 15:51:11 +09:00
type NoK8sNetworkError struct {
message string
}
2018-04-20 18:30:12 +01:00
2019-06-24 16:57:03 +09:00
// ClientInfo contains information given from k8s client
type ClientInfo struct {
2020-03-04 16:42:29 +09:00
Client kubernetes . Interface
NetClient netclient . K8sCniCncfIoV1Interface
EventBroadcaster record . EventBroadcaster
EventRecorder record . EventRecorder
2018-07-30 11:59:13 +01:00
}
2019-12-05 15:43:27 +09:00
// AddPod adds pod into kubernetes
2019-12-04 18:21:06 +09:00
func ( c * ClientInfo ) AddPod ( pod * v1 . Pod ) ( * v1 . Pod , error ) {
2020-10-23 10:54:20 -04:00
return c . Client . CoreV1 ( ) . Pods ( pod . ObjectMeta . Namespace ) . Create ( context . TODO ( ) , pod , metav1 . CreateOptions { } )
2018-06-14 13:15:02 -05:00
}
2019-12-05 15:43:27 +09:00
// GetPod gets pod from kubernetes
2019-12-04 18:21:06 +09:00
func ( c * ClientInfo ) GetPod ( namespace , name string ) ( * v1 . Pod , error ) {
2020-10-23 10:54:20 -04:00
return c . Client . CoreV1 ( ) . Pods ( namespace ) . Get ( context . TODO ( ) , name , metav1 . GetOptions { } )
2018-06-14 13:15:02 -05:00
}
2018-04-20 18:30:12 +01:00
2019-12-05 15:43:27 +09:00
// DeletePod deletes a pod from kubernetes
2019-12-04 18:21:06 +09:00
func ( c * ClientInfo ) DeletePod ( namespace , name string ) error {
2020-10-23 10:54:20 -04:00
return c . Client . CoreV1 ( ) . Pods ( namespace ) . Delete ( context . TODO ( ) , name , metav1 . DeleteOptions { } )
2018-06-14 13:15:02 -05:00
}
2019-12-05 15:43:27 +09:00
// AddNetAttachDef adds net-attach-def into kubernetes
2019-12-04 18:21:06 +09:00
func ( c * ClientInfo ) AddNetAttachDef ( netattach * nettypes . NetworkAttachmentDefinition ) ( * nettypes . NetworkAttachmentDefinition , error ) {
2020-10-23 10:54:20 -04:00
return c . NetClient . NetworkAttachmentDefinitions ( netattach . ObjectMeta . Namespace ) . Create ( context . TODO ( ) , netattach , metav1 . CreateOptions { } )
2018-07-30 11:59:13 +01:00
}
2020-03-04 16:42:29 +09:00
// Eventf puts event into kubernetes events
func ( c * ClientInfo ) Eventf ( object runtime . Object , eventtype , reason , messageFmt string , args ... interface { } ) {
if c != nil && c . EventRecorder != nil {
c . EventRecorder . Eventf ( object , eventtype , reason , messageFmt , args ... )
}
}
2022-04-18 21:34:40 +08:00
func ( e * NoK8sNetworkError ) Error ( ) string { return e . message }
2019-12-04 18:21:06 +09:00
2019-06-24 16:57:03 +09:00
// SetNetworkStatus sets network status into Pod annotation
2019-12-05 15:43:27 +09:00
func SetNetworkStatus ( client * ClientInfo , k8sArgs * types . K8sArgs , netStatus [ ] nettypes . NetworkStatus , conf * types . NetConf ) error {
thick-plugin: refactor multus
Multus is refactored as a thick plugin, featuring 2 main components:
- a server listening to a unix domain socket, running in a pod
- a shim, a binary on the host that will send JSON requests built from
its environment / stdin values to the aforementioned server.
The pod where the multus daemon is running must share the host's PID
namespace.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
react to maintainers review
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, deployment: update the daemonset spec
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, config: validate the cni config passed by the runtime
Without this patch, we're blindly trusting anything sent by the server.
This way, we assure the requests arriving at the multus controller are
valid before hand.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick: model client / server config
Also add a new command line parameter on the multus controller, pointing
it to the server configuration.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
SQUASH candidate, thick, config: cleanup the configuration
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
multus: use args.args instead of an env variable
CNI is already filling the args structure; we should consume that
rather than rely on the environment variables.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
unit tests: remove weird tests that check an impossible scenario
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
docs, thick: document the thick plugin variant
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, server, multus: re-use common types
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2021-12-16 18:18:35 +01:00
podName := string ( k8sArgs . K8S_POD_NAME )
podNamespace := string ( k8sArgs . K8S_POD_NAMESPACE )
podUID := string ( k8sArgs . K8S_POD_UID )
return SetPodNetworkStatusAnnotation ( client , podName , podNamespace , podUID , netStatus , conf )
}
// SetPodNetworkStatusAnnotation sets network status into Pod annotation
func SetPodNetworkStatusAnnotation ( client * ClientInfo , podName string , podNamespace string , podUID string , netStatus [ ] nettypes . NetworkStatus , conf * types . NetConf ) error {
2019-12-04 18:21:06 +09:00
var err error
thick-plugin: refactor multus
Multus is refactored as a thick plugin, featuring 2 main components:
- a server listening to a unix domain socket, running in a pod
- a shim, a binary on the host that will send JSON requests built from
its environment / stdin values to the aforementioned server.
The pod where the multus daemon is running must share the host's PID
namespace.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
react to maintainers review
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, deployment: update the daemonset spec
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, config: validate the cni config passed by the runtime
Without this patch, we're blindly trusting anything sent by the server.
This way, we assure the requests arriving at the multus controller are
valid before hand.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick: model client / server config
Also add a new command line parameter on the multus controller, pointing
it to the server configuration.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
SQUASH candidate, thick, config: cleanup the configuration
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
multus: use args.args instead of an env variable
CNI is already filling the args structure; we should consume that
rather than rely on the environment variables.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
unit tests: remove weird tests that check an impossible scenario
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
docs, thick: document the thick plugin variant
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, server, multus: re-use common types
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2021-12-16 18:18:35 +01:00
logging . Debugf ( "SetPodNetworkStatusAnnotation: %v, %v, %v" , client , netStatus , conf )
2019-03-20 14:08:48 +02:00
2019-12-04 18:21:06 +09:00
client , err = GetK8sClient ( conf . Kubeconfig , client )
2019-03-20 14:08:48 +02:00
if err != nil {
return logging . Errorf ( "SetNetworkStatus: %v" , err )
}
2019-12-04 18:21:06 +09:00
if client == nil || client . Client == nil {
2019-03-20 14:08:48 +02:00
if len ( conf . Delegates ) == 0 {
// No available kube client and no delegates, we can't do anything
2019-10-02 18:02:26 +09:00
return logging . Errorf ( "SetNetworkStatus: must have either Kubernetes config or delegates" )
2019-03-20 14:08:48 +02:00
}
thick-plugin: refactor multus
Multus is refactored as a thick plugin, featuring 2 main components:
- a server listening to a unix domain socket, running in a pod
- a shim, a binary on the host that will send JSON requests built from
its environment / stdin values to the aforementioned server.
The pod where the multus daemon is running must share the host's PID
namespace.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
react to maintainers review
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, deployment: update the daemonset spec
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, config: validate the cni config passed by the runtime
Without this patch, we're blindly trusting anything sent by the server.
This way, we assure the requests arriving at the multus controller are
valid before hand.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick: model client / server config
Also add a new command line parameter on the multus controller, pointing
it to the server configuration.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
SQUASH candidate, thick, config: cleanup the configuration
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
multus: use args.args instead of an env variable
CNI is already filling the args structure; we should consume that
rather than rely on the environment variables.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
unit tests: remove weird tests that check an impossible scenario
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
docs, thick: document the thick plugin variant
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, server, multus: re-use common types
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2021-12-16 18:18:35 +01:00
logging . Debugf ( "SetPodNetworkStatusAnnotation: kube client info is not defined, skip network status setup" )
2019-03-20 14:08:48 +02:00
return nil
}
2018-07-30 11:59:13 +01:00
2019-12-05 15:43:27 +09:00
pod , err := client . GetPod ( podNamespace , podName )
2018-07-30 11:59:13 +01:00
if err != nil {
thick-plugin: refactor multus
Multus is refactored as a thick plugin, featuring 2 main components:
- a server listening to a unix domain socket, running in a pod
- a shim, a binary on the host that will send JSON requests built from
its environment / stdin values to the aforementioned server.
The pod where the multus daemon is running must share the host's PID
namespace.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
react to maintainers review
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, deployment: update the daemonset spec
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, config: validate the cni config passed by the runtime
Without this patch, we're blindly trusting anything sent by the server.
This way, we assure the requests arriving at the multus controller are
valid before hand.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick: model client / server config
Also add a new command line parameter on the multus controller, pointing
it to the server configuration.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
SQUASH candidate, thick, config: cleanup the configuration
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
multus: use args.args instead of an env variable
CNI is already filling the args structure; we should consume that
rather than rely on the environment variables.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
unit tests: remove weird tests that check an impossible scenario
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
docs, thick: document the thick plugin variant
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, server, multus: re-use common types
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2021-12-16 18:18:35 +01:00
return logging . Errorf ( "SetPodNetworkStatusAnnotation: failed to query the pod %v in out of cluster comm: %v" , podName , err )
2018-07-30 11:59:13 +01:00
}
2022-01-13 16:41:14 +09:00
if podUID != "" && string ( pod . UID ) != podUID && ! IsStaticPod ( pod ) {
2021-10-21 10:44:29 -05:00
return logging . Errorf ( "SetNetworkStatus: expected pod %s/%s UID %q but got %q from Kube API" , podNamespace , podName , podUID , pod . UID )
}
2018-07-30 11:59:13 +01:00
if netStatus != nil {
2019-12-05 15:43:27 +09:00
err = netutils . SetNetworkStatus ( client . Client , pod , netStatus )
if err != nil {
thick-plugin: refactor multus
Multus is refactored as a thick plugin, featuring 2 main components:
- a server listening to a unix domain socket, running in a pod
- a shim, a binary on the host that will send JSON requests built from
its environment / stdin values to the aforementioned server.
The pod where the multus daemon is running must share the host's PID
namespace.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
react to maintainers review
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, deployment: update the daemonset spec
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, config: validate the cni config passed by the runtime
Without this patch, we're blindly trusting anything sent by the server.
This way, we assure the requests arriving at the multus controller are
valid before hand.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick: model client / server config
Also add a new command line parameter on the multus controller, pointing
it to the server configuration.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
SQUASH candidate, thick, config: cleanup the configuration
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
multus: use args.args instead of an env variable
CNI is already filling the args structure; we should consume that
rather than rely on the environment variables.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
unit tests: remove weird tests that check an impossible scenario
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
docs, thick: document the thick plugin variant
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, server, multus: re-use common types
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2021-12-16 18:18:35 +01:00
return logging . Errorf ( "SetPodNetworkStatusAnnotation: failed to update the pod %v in out of cluster comm: %v" , podName , err )
2018-07-30 11:59:13 +01:00
}
}
return nil
}
2018-04-20 18:30:12 +01:00
func parsePodNetworkObjectName ( podnetwork string ) ( string , string , string , error ) {
var netNsName string
var netIfName string
var networkName string
2018-08-06 15:55:30 +09:00
logging . Debugf ( "parsePodNetworkObjectName: %s" , podnetwork )
2018-04-20 18:30:12 +01:00
slashItems := strings . Split ( podnetwork , "/" )
if len ( slashItems ) == 2 {
netNsName = strings . TrimSpace ( slashItems [ 0 ] )
networkName = slashItems [ 1 ]
} else if len ( slashItems ) == 1 {
networkName = slashItems [ 0 ]
} else {
2019-10-02 18:02:26 +09:00
return "" , "" , "" , logging . Errorf ( "parsePodNetworkObjectName: Invalid network object (failed at '/')" )
2018-04-20 18:30:12 +01:00
}
atItems := strings . Split ( networkName , "@" )
networkName = strings . TrimSpace ( atItems [ 0 ] )
if len ( atItems ) == 2 {
netIfName = strings . TrimSpace ( atItems [ 1 ] )
} else if len ( atItems ) != 1 {
2019-10-02 18:02:26 +09:00
return "" , "" , "" , logging . Errorf ( "parsePodNetworkObjectName: Invalid network object (failed at '@')" )
2018-04-20 18:30:12 +01:00
}
2018-05-03 16:36:49 -04:00
// Check and see if each item matches the specification for valid attachment name.
// "Valid attachment names must be comprised of units of the DNS-1123 label format"
// [a-z0-9]([-a-z0-9]*[a-z0-9])?
// And we allow at (@), and forward slash (/) (units separated by commas)
// It must start and end alphanumerically.
allItems := [ ] string { netNsName , networkName , netIfName }
for i := range allItems {
matched , _ := regexp . MatchString ( "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" , allItems [ i ] )
2018-05-09 11:47:37 +01:00
if ! matched && len ( [ ] rune ( allItems [ i ] ) ) > 0 {
2019-10-02 18:02:26 +09:00
return "" , "" , "" , logging . Errorf ( fmt . Sprintf ( "parsePodNetworkObjectName: Failed to parse: one or more items did not match comma-delimited format (must consist of lower case alphanumeric characters). Must start and end with an alphanumeric character), mismatch @ '%v'" , allItems [ i ] ) )
2018-05-03 16:36:49 -04:00
}
}
2018-08-06 15:55:30 +09:00
logging . Debugf ( "parsePodNetworkObjectName: parsed: %s, %s, %s" , netNsName , networkName , netIfName )
2018-04-20 18:30:12 +01:00
return netNsName , networkName , netIfName , nil
}
2018-06-19 21:27:42 -05:00
func parsePodNetworkAnnotation ( podNetworks , defaultNamespace string ) ( [ ] * types . NetworkSelectionElement , error ) {
var networks [ ] * types . NetworkSelectionElement
2018-04-20 18:30:12 +01:00
2018-08-06 15:55:30 +09:00
logging . Debugf ( "parsePodNetworkAnnotation: %s, %s" , podNetworks , defaultNamespace )
2018-06-19 21:27:42 -05:00
if podNetworks == "" {
2019-10-02 18:02:26 +09:00
return nil , logging . Errorf ( "parsePodNetworkAnnotation: pod annotation does not have \"network\" as key" )
2018-04-20 18:30:12 +01:00
}
2018-06-19 21:27:42 -05:00
if strings . IndexAny ( podNetworks , "[{\"" ) >= 0 {
if err := json . Unmarshal ( [ ] byte ( podNetworks ) , & networks ) ; err != nil {
2018-08-06 15:55:30 +09:00
return nil , logging . Errorf ( "parsePodNetworkAnnotation: failed to parse pod Network Attachment Selection Annotation JSON format: %v" , err )
2018-06-19 21:27:42 -05:00
}
} else {
// Comma-delimited list of network attachment object names
for _ , item := range strings . Split ( podNetworks , "," ) {
2018-05-03 16:36:49 -04:00
// Remove leading and trailing whitespace.
2018-06-19 21:27:42 -05:00
item = strings . TrimSpace ( item )
2018-05-03 16:36:49 -04:00
2018-04-20 18:30:12 +01:00
// Parse network name (i.e. <namespace>/<network name>@<ifname>)
2018-06-19 21:27:42 -05:00
netNsName , networkName , netIfName , err := parsePodNetworkObjectName ( item )
2018-04-20 18:30:12 +01:00
if err != nil {
2018-08-06 15:55:30 +09:00
return nil , logging . Errorf ( "parsePodNetworkAnnotation: %v" , err )
2018-04-20 18:30:12 +01:00
}
2018-06-19 21:27:42 -05:00
networks = append ( networks , & types . NetworkSelectionElement {
Name : networkName ,
Namespace : netNsName ,
InterfaceRequest : netIfName ,
} )
2018-04-20 18:30:12 +01:00
}
}
2019-08-16 18:55:12 +09:00
for _ , n := range networks {
if n . Namespace == "" {
n . Namespace = defaultNamespace
2018-06-19 21:27:42 -05:00
}
2019-08-16 18:55:12 +09:00
if n . MacRequest != "" {
// validate MAC address
if _ , err := net . ParseMAC ( n . MacRequest ) ; err != nil {
return nil , logging . Errorf ( "parsePodNetworkAnnotation: failed to mac: %v" , err )
}
}
2020-04-27 10:23:26 +03:00
if n . InfinibandGUIDRequest != "" {
// validate GUID address
if _ , err := net . ParseMAC ( n . InfinibandGUIDRequest ) ; err != nil {
return nil , logging . Errorf ( "parsePodNetworkAnnotation: failed to validate infiniband GUID: %v" , err )
}
}
2019-08-16 18:55:12 +09:00
if n . IPRequest != nil {
for _ , ip := range n . IPRequest {
// validate IP address
if strings . Contains ( ip , "/" ) {
if _ , _ , err := net . ParseCIDR ( ip ) ; err != nil {
return nil , logging . Errorf ( "failed to parse CIDR %q: %v" , ip , err )
}
} else if net . ParseIP ( ip ) == nil {
return nil , logging . Errorf ( "failed to parse IP address %q" , ip )
}
}
}
// compatibility pre v3.2, will be removed in v4.0
if n . DeprecatedInterfaceRequest != "" && n . InterfaceRequest == "" {
n . InterfaceRequest = n . DeprecatedInterfaceRequest
2019-08-23 00:19:06 +09:00
}
2018-06-19 21:27:42 -05:00
}
return networks , nil
2018-04-20 18:30:12 +01:00
}
2019-12-04 18:21:06 +09:00
func getKubernetesDelegate ( client * ClientInfo , net * types . NetworkSelectionElement , confdir string , pod * v1 . Pod , resourceMap map [ string ] * types . ResourceInfo ) ( * types . DelegateNetConf , map [ string ] * types . ResourceInfo , error ) {
2018-09-10 16:27:07 +01:00
2019-12-04 18:21:06 +09:00
logging . Debugf ( "getKubernetesDelegate: %v, %v, %s, %v, %v" , client , net , confdir , pod , resourceMap )
2020-10-23 10:54:20 -04:00
customResource , err := client . NetClient . NetworkAttachmentDefinitions ( net . Namespace ) . Get ( context . TODO ( ) , net . Name , metav1 . GetOptions { } )
2018-04-20 18:30:12 +01:00
if err != nil {
2020-04-01 20:08:02 +09:00
errMsg := fmt . Sprintf ( "cannot find a network-attachment-definition (%s) in namespace (%s): %v" , net . Name , net . Namespace , err )
2020-03-18 17:21:43 +09:00
if client != nil {
2020-04-01 20:08:02 +09:00
client . Eventf ( pod , v1 . EventTypeWarning , "NoNetworkFound" , errMsg )
2020-03-18 17:21:43 +09:00
}
2020-04-01 20:08:02 +09:00
return nil , resourceMap , logging . Errorf ( "getKubernetesDelegate: " + errMsg )
2018-04-20 18:30:12 +01:00
}
2018-10-01 10:38:56 +01:00
// Get resourceName annotation from NetworkAttachmentDefinition
2018-09-10 16:27:07 +01:00
deviceID := ""
2019-09-19 10:36:52 -04:00
resourceName , ok := customResource . GetAnnotations ( ) [ resourceNameAnnot ]
2019-02-07 15:48:40 +00:00
if ok && pod . Name != "" && pod . Namespace != "" {
2018-09-10 16:27:07 +01:00
// ResourceName annotation is found; try to get device info from resourceMap
2018-09-19 16:41:08 +01:00
logging . Debugf ( "getKubernetesDelegate: found resourceName annotation : %s" , resourceName )
if resourceMap == nil {
2021-05-22 03:39:43 +09:00
ck , err := kubeletclient . GetResourceClient ( "" )
2018-09-19 16:41:08 +01:00
if err != nil {
2019-02-07 15:48:40 +00:00
return nil , resourceMap , logging . Errorf ( "getKubernetesDelegate: failed to get a ResourceClient instance: %v" , err )
2018-09-19 16:41:08 +01:00
}
2019-02-07 15:48:40 +00:00
resourceMap , err = ck . GetPodResourceMap ( pod )
2018-09-19 16:41:08 +01:00
if err != nil {
2019-02-07 15:48:40 +00:00
return nil , resourceMap , logging . Errorf ( "getKubernetesDelegate: failed to get resourceMap from ResourceClient: %v" , err )
2018-09-19 16:41:08 +01:00
}
2019-10-02 18:02:26 +09:00
logging . Debugf ( "getKubernetesDelegate: resourceMap instance: %+v" , resourceMap )
2018-09-18 13:14:58 +01:00
}
2018-09-10 16:27:07 +01:00
entry , ok := resourceMap [ resourceName ]
if ok {
if idCount := len ( entry . DeviceIDs ) ; idCount > 0 && idCount > entry . Index {
deviceID = entry . DeviceIDs [ entry . Index ]
2019-02-07 15:48:40 +00:00
logging . Debugf ( "getKubernetesDelegate: podName: %s deviceID: %s" , pod . Name , deviceID )
2018-09-10 16:27:07 +01:00
entry . Index ++ // increment Index for next delegate
}
}
}
2019-12-05 15:43:27 +09:00
configBytes , err := netutils . GetCNIConfig ( customResource , confdir )
2018-04-20 18:30:12 +01:00
if err != nil {
2018-09-18 13:14:58 +01:00
return nil , resourceMap , err
2018-04-20 18:30:12 +01:00
}
2020-11-03 09:42:30 -05:00
delegate , err := types . LoadDelegateNetConf ( configBytes , net , deviceID , resourceName )
2018-05-01 13:08:39 -05:00
if err != nil {
2018-09-18 13:14:58 +01:00
return nil , resourceMap , err
2018-04-20 18:30:12 +01:00
}
2018-09-18 13:14:58 +01:00
return delegate , resourceMap , nil
2018-08-03 13:32:28 +01:00
}
2019-06-24 16:57:03 +09:00
// GetK8sArgs gets k8s related args from CNI args
2018-07-27 00:04:52 +01:00
func GetK8sArgs ( args * skel . CmdArgs ) ( * types . K8sArgs , error ) {
k8sArgs := & types . K8sArgs { }
2018-10-11 17:57:20 +09:00
logging . Debugf ( "GetK8sArgs: %v" , args )
2018-07-27 00:04:52 +01:00
err := cnitypes . LoadArgs ( args . Args , k8sArgs )
if err != nil {
return nil , err
}
return k8sArgs , nil
}
2019-06-24 16:57:03 +09:00
// TryLoadPodDelegates attempts to load Kubernetes-defined delegates and add them to the Multus config.
2018-07-30 11:59:13 +01:00
// Returns the number of Kubernetes-defined delegates added or an error.
2020-05-18 18:16:51 +09:00
func TryLoadPodDelegates ( pod * v1 . Pod , conf * types . NetConf , clientInfo * ClientInfo , resourceMap map [ string ] * types . ResourceInfo ) ( int , * ClientInfo , error ) {
2018-07-30 11:59:13 +01:00
var err error
2020-05-18 18:16:51 +09:00
logging . Debugf ( "TryLoadPodDelegates: %v, %v, %v" , pod , conf , clientInfo )
2019-12-04 18:21:06 +09:00
clientInfo , err = GetK8sClient ( conf . Kubeconfig , clientInfo )
2018-07-30 11:59:13 +01:00
if err != nil {
2020-05-18 18:16:51 +09:00
return 0 , nil , err
2018-07-30 11:59:13 +01:00
}
2019-12-04 18:21:06 +09:00
if clientInfo == nil {
2018-07-30 11:59:13 +01:00
if len ( conf . Delegates ) == 0 {
// No available kube client and no delegates, we can't do anything
2020-05-18 18:16:51 +09:00
return 0 , nil , logging . Errorf ( "TryLoadPodDelegates: must have either Kubernetes config or delegates" )
2018-07-30 11:59:13 +01:00
}
2020-05-18 18:16:51 +09:00
return 0 , nil , nil
2019-01-25 17:49:16 +09:00
}
2018-09-28 15:02:05 +08:00
2019-12-04 18:21:06 +09:00
delegate , err := tryLoadK8sPodDefaultNetwork ( clientInfo , pod , conf )
2018-09-28 15:02:05 +08:00
if err != nil {
2020-05-18 18:16:51 +09:00
return 0 , nil , logging . Errorf ( "TryLoadPodDelegates: error in loading K8s cluster default network from pod annotation: %v" , err )
2018-11-27 08:38:36 +08:00
}
2018-12-18 17:03:05 -05:00
if delegate != nil {
2019-10-02 18:02:26 +09:00
logging . Debugf ( "TryLoadPodDelegates: Overwrite the cluster default network with %v from pod annotations" , delegate )
2018-11-27 08:38:36 +08:00
2018-09-28 15:02:05 +08:00
conf . Delegates [ 0 ] = delegate
}
2019-01-25 17:49:16 +09:00
networks , err := GetPodNetwork ( pod )
if networks != nil {
2020-10-29 13:10:12 -04:00
delegates , err := GetNetworkDelegates ( clientInfo , pod , networks , conf , resourceMap )
2019-01-25 17:49:16 +09:00
if err != nil {
if _ , ok := err . ( * NoK8sNetworkError ) ; ok {
2020-05-18 18:16:51 +09:00
return 0 , clientInfo , nil
2019-01-25 17:49:16 +09:00
}
2020-05-18 18:16:51 +09:00
return 0 , nil , logging . Errorf ( "TryLoadPodDelegates: error in getting k8s network for pod: %v" , err )
2018-07-30 11:59:13 +01:00
}
2019-01-25 17:49:16 +09:00
if err = conf . AddDelegates ( delegates ) ; err != nil {
2020-05-18 18:16:51 +09:00
return 0 , nil , err
2019-01-25 17:49:16 +09:00
}
2019-08-27 16:52:58 +09:00
// Check gatewayRequest is configured in delegates
// and mark its config if gateway filter is required
isGatewayConfigured := false
for _ , delegate := range conf . Delegates {
if delegate . GatewayRequest != nil {
isGatewayConfigured = true
break
}
}
if isGatewayConfigured == true {
2021-12-04 00:48:50 +09:00
err = types . CheckGatewayConfig ( conf . Delegates )
if err != nil {
return 0 , nil , err
}
2019-08-27 16:52:58 +09:00
}
2021-12-04 00:48:50 +09:00
return len ( delegates ) , clientInfo , err
2018-07-30 11:59:13 +01:00
}
2019-08-27 16:52:58 +09:00
2021-03-31 22:06:21 +09:00
if _ , ok := err . ( * NoK8sNetworkError ) ; ok {
return 0 , clientInfo , nil
}
2021-03-26 01:31:01 +09:00
return 0 , clientInfo , err
2018-07-30 11:59:13 +01:00
}
thick-plugin: refactor multus
Multus is refactored as a thick plugin, featuring 2 main components:
- a server listening to a unix domain socket, running in a pod
- a shim, a binary on the host that will send JSON requests built from
its environment / stdin values to the aforementioned server.
The pod where the multus daemon is running must share the host's PID
namespace.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
react to maintainers review
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, deployment: update the daemonset spec
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, config: validate the cni config passed by the runtime
Without this patch, we're blindly trusting anything sent by the server.
This way, we assure the requests arriving at the multus controller are
valid before hand.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick: model client / server config
Also add a new command line parameter on the multus controller, pointing
it to the server configuration.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
SQUASH candidate, thick, config: cleanup the configuration
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
multus: use args.args instead of an env variable
CNI is already filling the args structure; we should consume that
rather than rely on the environment variables.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
unit tests: remove weird tests that check an impossible scenario
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
docs, thick: document the thick plugin variant
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, server, multus: re-use common types
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2021-12-16 18:18:35 +01:00
// InClusterK8sClient returns the `k8s.ClientInfo` struct to use to connect to
// the k8s API.
func InClusterK8sClient ( ) ( * ClientInfo , error ) {
config , err := rest . InClusterConfig ( )
if err != nil {
return nil , err
}
logging . Debugf ( "InClusterK8sClient: in cluster config: %+v" , config )
return NewClientInfo ( config )
}
2019-06-24 16:57:03 +09:00
// GetK8sClient gets client info from kubeconfig
2019-12-04 18:21:06 +09:00
func GetK8sClient ( kubeconfig string , kubeClient * ClientInfo ) ( * ClientInfo , error ) {
2018-08-06 15:55:30 +09:00
logging . Debugf ( "GetK8sClient: %s, %v" , kubeconfig , kubeClient )
2018-07-19 09:02:49 -05:00
// If we get a valid kubeClient (eg from testcases) just return that
// one.
if kubeClient != nil {
return kubeClient , nil
}
2018-04-20 18:30:12 +01:00
2018-07-19 09:02:49 -05:00
var err error
var config * rest . Config
// Otherwise try to create a kubeClient from a given kubeConfig
if kubeconfig != "" {
// uses the current context in kubeconfig
config , err = clientcmd . BuildConfigFromFlags ( "" , kubeconfig )
if err != nil {
2019-10-02 18:02:26 +09:00
return nil , logging . Errorf ( "GetK8sClient: failed to get context for the kubeconfig %v: %v" , kubeconfig , err )
2018-07-19 09:02:49 -05:00
}
} else if os . Getenv ( "KUBERNETES_SERVICE_HOST" ) != "" && os . Getenv ( "KUBERNETES_SERVICE_PORT" ) != "" {
// Try in-cluster config where multus might be running in a kubernetes pod
config , err = rest . InClusterConfig ( )
if err != nil {
2019-10-02 18:02:26 +09:00
return nil , logging . Errorf ( "GetK8sClient: failed to get context for in-cluster kube config: %v" , err )
2018-07-19 09:02:49 -05:00
}
} else {
// No kubernetes config; assume we shouldn't talk to Kube at all
return nil , nil
}
2019-02-12 10:24:00 -05:00
// Specify that we use gRPC
config . AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json"
config . ContentType = "application/vnd.kubernetes.protobuf"
2020-04-22 13:51:42 -04:00
// Set the config timeout to one minute.
config . Timeout = time . Minute
2019-02-12 10:24:00 -05:00
thick-plugin: refactor multus
Multus is refactored as a thick plugin, featuring 2 main components:
- a server listening to a unix domain socket, running in a pod
- a shim, a binary on the host that will send JSON requests built from
its environment / stdin values to the aforementioned server.
The pod where the multus daemon is running must share the host's PID
namespace.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
react to maintainers review
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, deployment: update the daemonset spec
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, config: validate the cni config passed by the runtime
Without this patch, we're blindly trusting anything sent by the server.
This way, we assure the requests arriving at the multus controller are
valid before hand.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick: model client / server config
Also add a new command line parameter on the multus controller, pointing
it to the server configuration.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
SQUASH candidate, thick, config: cleanup the configuration
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
multus: use args.args instead of an env variable
CNI is already filling the args structure; we should consume that
rather than rely on the environment variables.
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
unit tests: remove weird tests that check an impossible scenario
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
docs, thick: document the thick plugin variant
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
thick, server, multus: re-use common types
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2021-12-16 18:18:35 +01:00
return NewClientInfo ( config )
}
// NewClientInfo returns a `ClientInfo` from a configuration created from an
// existing kubeconfig file.
func NewClientInfo ( config * rest . Config ) ( * ClientInfo , error ) {
2018-07-19 09:02:49 -05:00
client , err := kubernetes . NewForConfig ( config )
2018-04-20 18:30:12 +01:00
if err != nil {
2018-05-01 13:08:39 -05:00
return nil , err
2018-04-20 18:30:12 +01:00
}
2019-12-04 18:21:06 +09:00
netclient , err := netclient . NewForConfig ( config )
if err != nil {
return nil , err
}
2020-03-04 16:42:29 +09:00
broadcaster := record . NewBroadcaster ( )
broadcaster . StartLogging ( klog . Infof )
broadcaster . StartRecordingToSink ( & v1core . EventSinkImpl { Interface : client . CoreV1 ( ) . Events ( "" ) } )
recorder := broadcaster . NewRecorder ( scheme . Scheme , v1 . EventSource { Component : "multus" } )
2019-12-04 18:21:06 +09:00
return & ClientInfo {
2020-03-04 16:42:29 +09:00
Client : client ,
NetClient : netclient ,
EventBroadcaster : broadcaster ,
EventRecorder : recorder ,
2019-12-04 18:21:06 +09:00
} , nil
2018-07-19 09:02:49 -05:00
}
2019-06-24 16:57:03 +09:00
// GetPodNetwork gets net-attach-def annotation from pod
2019-01-25 17:49:16 +09:00
func GetPodNetwork ( pod * v1 . Pod ) ( [ ] * types . NetworkSelectionElement , error ) {
logging . Debugf ( "GetPodNetwork: %v" , pod )
2018-04-20 18:30:12 +01:00
2019-01-25 17:49:16 +09:00
netAnnot := pod . Annotations [ networkAttachmentAnnot ]
defaultNamespace := pod . ObjectMeta . Namespace
2018-09-10 16:27:07 +01:00
2018-04-20 18:30:12 +01:00
if len ( netAnnot ) == 0 {
2018-05-01 13:08:39 -05:00
return nil , & NoK8sNetworkError { "no kubernetes network found" }
2018-04-20 18:30:12 +01:00
}
2018-06-19 21:27:42 -05:00
networks , err := parsePodNetworkAnnotation ( netAnnot , defaultNamespace )
2018-04-20 18:30:12 +01:00
if err != nil {
2018-05-01 13:08:39 -05:00
return nil , err
2018-04-20 18:30:12 +01:00
}
2019-01-25 17:49:16 +09:00
return networks , nil
}
2018-04-20 18:30:12 +01:00
2019-06-24 16:57:03 +09:00
// GetNetworkDelegates returns delegatenetconf from net-attach-def annotation in pod
2020-10-29 13:10:12 -04:00
func GetNetworkDelegates ( k8sclient * ClientInfo , pod * v1 . Pod , networks [ ] * types . NetworkSelectionElement , conf * types . NetConf , resourceMap map [ string ] * types . ResourceInfo ) ( [ ] * types . DelegateNetConf , error ) {
logging . Debugf ( "GetNetworkDelegates: %v, %v, %v, %v, %v" , k8sclient , pod , networks , conf , resourceMap )
2018-06-19 21:27:42 -05:00
// Read all network objects referenced by 'networks'
var delegates [ ] * types . DelegateNetConf
2019-01-25 17:49:16 +09:00
defaultNamespace := pod . ObjectMeta . Namespace
2018-06-19 21:27:42 -05:00
for _ , net := range networks {
2018-12-18 17:03:05 -05:00
// The pods namespace (stored as defaultNamespace, does not equal the annotation's target namespace in net.Namespace)
// In the case that this is a mismatch when namespaceisolation is enabled, this should be an error.
2020-10-29 13:10:12 -04:00
if conf . NamespaceIsolation {
2018-12-18 17:03:05 -05:00
if defaultNamespace != net . Namespace {
2020-10-29 13:10:12 -04:00
// We allow exceptions based on the specified list of non-isolated namespaces (and/or "default" namespace, by default)
if ! isValidNamespaceReference ( net . Namespace , conf . NonIsolatedNamespaces ) {
2020-04-21 14:19:39 -04:00
return nil , logging . Errorf ( "GetNetworkDelegates: namespace isolation enabled, annotation violates permission, pod is in namespace %v but refers to target namespace %v" , defaultNamespace , net . Namespace )
}
2018-12-18 17:03:05 -05:00
}
}
2020-10-29 13:10:12 -04:00
delegate , updatedResourceMap , err := getKubernetesDelegate ( k8sclient , net , conf . ConfDir , pod , resourceMap )
2018-06-19 21:27:42 -05:00
if err != nil {
2019-10-02 18:02:26 +09:00
return nil , logging . Errorf ( "GetNetworkDelegates: failed getting the delegate: %v" , err )
2018-06-19 21:27:42 -05:00
}
delegates = append ( delegates , delegate )
2018-09-19 16:41:08 +01:00
resourceMap = updatedResourceMap
2018-04-20 18:30:12 +01:00
}
2018-06-19 21:27:42 -05:00
return delegates , nil
2018-04-20 18:30:12 +01:00
}
2018-10-11 17:57:20 +09:00
2020-10-29 13:10:12 -04:00
func isValidNamespaceReference ( targetns string , allowednamespaces [ ] string ) bool {
for _ , eachns := range allowednamespaces {
if eachns == targetns {
return true
}
}
return false
}
2022-03-23 02:36:34 +09:00
// getNetDelegate loads delegate network for clusterNetwork/defaultNetworks
2020-05-18 18:16:51 +09:00
func getNetDelegate ( client * ClientInfo , pod * v1 . Pod , netname , confdir , namespace string , resourceMap map [ string ] * types . ResourceInfo ) ( * types . DelegateNetConf , map [ string ] * types . ResourceInfo , error ) {
2019-02-22 11:50:37 +09:00
logging . Debugf ( "getNetDelegate: %v, %v, %v, %s" , client , netname , confdir , namespace )
2018-10-11 17:57:20 +09:00
var configBytes [ ] byte
2022-03-23 02:36:34 +09:00
isNetnamePath := strings . Contains ( netname , "/" )
// if netname is not directory or file, it must be net-attach-def name or CNI config name
2022-04-08 23:08:07 +09:00
if ! isNetnamePath {
2022-03-23 02:36:34 +09:00
// option1) search CRD object for the network
net := & types . NetworkSelectionElement {
Name : netname ,
Namespace : namespace ,
}
delegate , resourceMap , err := getKubernetesDelegate ( client , net , confdir , pod , resourceMap )
if err == nil {
return delegate , resourceMap , nil
}
// option2) search CNI json config file, which has <netname> as CNI name, from confDir
configBytes , err = netutils . GetCNIConfigFromFile ( netname , confdir )
if err == nil {
delegate , err := types . LoadDelegateNetConf ( configBytes , nil , "" , "" )
if err != nil {
return nil , resourceMap , err
}
return delegate , resourceMap , nil
}
} else {
fInfo , err := os . Stat ( netname )
2018-10-11 17:57:20 +09:00
if err != nil {
2022-04-08 23:08:07 +09:00
return nil , resourceMap , err
2018-10-11 17:57:20 +09:00
}
2022-03-23 02:36:34 +09:00
// option3) search directory
2018-10-11 17:57:20 +09:00
if fInfo . IsDir ( ) {
files , err := libcni . ConfFiles ( netname , [ ] string { ".conf" , ".conflist" } )
2018-11-27 17:34:20 +01:00
if err != nil {
2020-05-18 18:16:51 +09:00
return nil , resourceMap , err
2018-11-27 17:34:20 +01:00
}
2018-10-15 16:32:15 +09:00
if len ( files ) > 0 {
2018-10-11 17:57:20 +09:00
var configBytes [ ] byte
2019-12-05 15:43:27 +09:00
configBytes , err = netutils . GetCNIConfigFromFile ( "" , netname )
2018-10-11 17:57:20 +09:00
if err == nil {
2020-11-03 09:42:30 -05:00
delegate , err := types . LoadDelegateNetConf ( configBytes , nil , "" , "" )
2018-10-11 17:57:20 +09:00
if err != nil {
2020-05-18 18:16:51 +09:00
return nil , resourceMap , err
2018-10-11 17:57:20 +09:00
}
2020-05-18 18:16:51 +09:00
return delegate , resourceMap , nil
2018-10-11 17:57:20 +09:00
}
2020-05-18 18:16:51 +09:00
return nil , resourceMap , err
2018-10-11 17:57:20 +09:00
}
2022-03-23 02:36:34 +09:00
} else {
// option4) if file path (absolute), then load it directly
if strings . HasSuffix ( netname , ".conflist" ) {
confList , err := libcni . ConfListFromFile ( netname )
if err != nil {
2022-04-08 23:08:07 +09:00
return nil , resourceMap , logging . Errorf ( "error loading CNI conflist file %s: %v" , netname , err )
2022-03-23 02:36:34 +09:00
}
configBytes = confList . Bytes
} else {
conf , err := libcni . ConfFromFile ( netname )
if err != nil {
2022-04-08 23:08:07 +09:00
return nil , resourceMap , logging . Errorf ( "error loading CNI config file %s: %v" , netname , err )
2022-03-23 02:36:34 +09:00
}
if conf . Network . Type == "" {
2022-04-08 23:08:07 +09:00
return nil , resourceMap , logging . Errorf ( "error loading CNI config file %s: no 'type'; perhaps this is a .conflist?" , netname )
2022-03-23 02:36:34 +09:00
}
configBytes = conf . Bytes
}
delegate , err := types . LoadDelegateNetConf ( configBytes , nil , "" , "" )
if err != nil {
return nil , resourceMap , err
}
return delegate , resourceMap , nil
2018-10-11 17:57:20 +09:00
}
}
2020-05-18 18:16:51 +09:00
return nil , resourceMap , logging . Errorf ( "getNetDelegate: cannot find network: %v" , netname )
2018-10-11 17:57:20 +09:00
}
2019-06-24 16:57:03 +09:00
// GetDefaultNetworks parses 'defaultNetwork' config, gets network json and put it into netconf.Delegates.
2020-05-18 18:16:51 +09:00
func GetDefaultNetworks ( pod * v1 . Pod , conf * types . NetConf , kubeClient * ClientInfo , resourceMap map [ string ] * types . ResourceInfo ) ( map [ string ] * types . ResourceInfo , error ) {
logging . Debugf ( "GetDefaultNetworks: %v, %v, %v, %v" , pod , conf , kubeClient , resourceMap )
2018-10-11 17:57:20 +09:00
var delegates [ ] * types . DelegateNetConf
kubeClient , err := GetK8sClient ( conf . Kubeconfig , kubeClient )
if err != nil {
2020-05-18 18:16:51 +09:00
return resourceMap , err
2018-10-11 17:57:20 +09:00
}
if kubeClient == nil {
if len ( conf . Delegates ) == 0 {
// No available kube client and no delegates, we can't do anything
2020-05-18 18:16:51 +09:00
return resourceMap , logging . Errorf ( "GetDefaultNetworks: must have either Kubernetes config or delegates" )
2018-10-11 17:57:20 +09:00
}
2020-05-18 18:16:51 +09:00
return resourceMap , nil
2018-10-11 17:57:20 +09:00
}
2020-05-18 18:16:51 +09:00
delegate , resourceMap , err := getNetDelegate ( kubeClient , pod , conf . ClusterNetwork , conf . ConfDir , conf . MultusNamespace , resourceMap )
2018-10-11 17:57:20 +09:00
if err != nil {
2020-05-18 18:16:51 +09:00
return resourceMap , logging . Errorf ( "GetDefaultNetworks: failed to get clusterNetwork %s in namespace %s" , conf . ClusterNetwork , conf . MultusNamespace )
2018-10-11 17:57:20 +09:00
}
delegate . MasterPlugin = true
delegates = append ( delegates , delegate )
2018-11-30 16:33:09 +09:00
// Pod in kube-system namespace does not have default network for now.
2020-05-18 18:16:51 +09:00
if ! types . CheckSystemNamespaces ( pod . ObjectMeta . Namespace , conf . SystemNamespaces ) {
2018-11-30 16:33:09 +09:00
for _ , netname := range conf . DefaultNetworks {
2020-05-18 18:16:51 +09:00
delegate , resourceMap , err := getNetDelegate ( kubeClient , pod , netname , conf . ConfDir , conf . MultusNamespace , resourceMap )
2018-11-30 16:33:09 +09:00
if err != nil {
2020-05-18 18:16:51 +09:00
return resourceMap , err
2018-11-30 16:33:09 +09:00
}
delegates = append ( delegates , delegate )
2018-10-11 17:57:20 +09:00
}
}
if err = conf . AddDelegates ( delegates ) ; err != nil {
2020-05-18 18:16:51 +09:00
return resourceMap , err
2018-10-11 17:57:20 +09:00
}
2020-05-18 18:16:51 +09:00
return resourceMap , nil
2018-10-11 17:57:20 +09:00
}
2018-09-28 15:02:05 +08:00
// tryLoadK8sPodDefaultNetwork get pod default network from annotations
2019-12-04 18:21:06 +09:00
func tryLoadK8sPodDefaultNetwork ( kubeClient * ClientInfo , pod * v1 . Pod , conf * types . NetConf ) ( * types . DelegateNetConf , error ) {
2019-01-25 17:49:16 +09:00
var netAnnot string
logging . Debugf ( "tryLoadK8sPodDefaultNetwork: %v, %v, %v" , kubeClient , pod , conf )
2018-09-28 15:02:05 +08:00
2019-01-25 17:49:16 +09:00
netAnnot , ok := pod . Annotations [ defaultNetAnnot ]
if ! ok {
2018-11-27 08:38:36 +08:00
logging . Debugf ( "tryLoadK8sPodDefaultNetwork: Pod default network annotation is not defined" )
2018-09-28 15:02:05 +08:00
return nil , nil
}
2019-02-22 11:50:37 +09:00
// The CRD object of default network should only be defined in multusNamespace
networks , err := parsePodNetworkAnnotation ( netAnnot , conf . MultusNamespace )
2018-09-28 15:02:05 +08:00
if err != nil {
2018-11-27 08:38:36 +08:00
return nil , logging . Errorf ( "tryLoadK8sPodDefaultNetwork: failed to parse CRD object: %v" , err )
2018-09-28 15:02:05 +08:00
}
if len ( networks ) > 1 {
return nil , logging . Errorf ( "tryLoadK8sPodDefaultNetwork: more than one default network is specified: %s" , netAnnot )
}
2019-02-07 15:48:40 +00:00
delegate , _ , err := getKubernetesDelegate ( kubeClient , networks [ 0 ] , conf . ConfDir , pod , nil )
2018-09-28 15:02:05 +08:00
if err != nil {
return nil , logging . Errorf ( "tryLoadK8sPodDefaultNetwork: failed getting the delegate: %v" , err )
}
delegate . MasterPlugin = true
return delegate , nil
}
2022-01-13 16:41:14 +09:00
// ConfigSourceAnnotationKey specifies kubernetes annotation, defined in k8s.io/kubernetes/pkg/kubelet/types
const ConfigSourceAnnotationKey = "kubernetes.io/config.source"
// IsStaticPod returns true if the pod is static pod.
func IsStaticPod ( pod * v1 . Pod ) bool {
if pod . Annotations != nil {
if source , ok := pod . Annotations [ ConfigSourceAnnotationKey ] ; ok == true {
return source != "api"
}
}
return false
}