mirror of
https://github.com/k8snetworkplumbingwg/multus-cni.git
synced 2025-10-24 09:17:24 +00:00
APIReadyCheckFunc is used only in api, hence it can be decapitalize to make its scope only in this package. This fix changes its scope. In addition, api.APIReadyCheckFunc seems to be redundant so the name is changed. Change the comment to fit to golang style, too.
144 lines
4.4 KiB
Go
144 lines
4.4 KiB
Go
// Copyright (c) 2022 Multus Authors
|
|
//
|
|
// 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 api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/containernetworking/cni/pkg/skel"
|
|
cnitypes "github.com/containernetworking/cni/pkg/types"
|
|
|
|
"gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/logging"
|
|
)
|
|
|
|
// ShimNetConf for the SHIM cni config file written in json
|
|
type ShimNetConf struct {
|
|
// Note: This struct contains NetConf in pkg/types, but this struct is only used to parse
|
|
// following fields, so we skip to include NetConf here. Other fields are directly send to
|
|
// multus-daemon as a part of skel.CmdArgs, StdinData.
|
|
// types.NetConf
|
|
|
|
CNIVersion string `json:"cniVersion,omitempty"`
|
|
MultusSocketDir string `json:"daemonSocketDir"`
|
|
LogFile string `json:"logFile,omitempty"`
|
|
LogLevel string `json:"logLevel,omitempty"`
|
|
LogToStderr bool `json:"logToStderr,omitempty"`
|
|
}
|
|
|
|
// readyCheckFunc defines a type for API readiness check functions
|
|
type readyCheckFunc func(string) error
|
|
|
|
// CmdAdd implements the CNI spec ADD command handler
|
|
func CmdAdd(args *skel.CmdArgs) error {
|
|
response, cniVersion, err := postRequest(args, WaitUntilAPIReady)
|
|
if err != nil {
|
|
return logging.Errorf("CmdAdd (shim): %v", err)
|
|
}
|
|
|
|
logging.Verbosef("CmdAdd (shim): %v", *response.Result)
|
|
return cnitypes.PrintResult(response.Result, cniVersion)
|
|
}
|
|
|
|
// CmdCheck implements the CNI spec CHECK command handler
|
|
func CmdCheck(args *skel.CmdArgs) error {
|
|
_, _, err := postRequest(args, WaitUntilAPIReady)
|
|
if err != nil {
|
|
return logging.Errorf("CmdCheck (shim): %v", err)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// CmdDel implements the CNI spec DEL command handler
|
|
func CmdDel(args *skel.CmdArgs) error {
|
|
_, _, err := postRequest(args, CheckAPIReadyNow)
|
|
if err != nil {
|
|
// No error in DEL (as of CNI spec)
|
|
logging.Errorf("CmdDel (shim): %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func postRequest(args *skel.CmdArgs, readinessCheck readyCheckFunc) (*Response, string, error) {
|
|
multusShimConfig, err := shimConfig(args.StdinData)
|
|
if err != nil {
|
|
return nil, "", fmt.Errorf("invalid CNI configuration passed to multus-shim: %w", err)
|
|
}
|
|
|
|
// Execute the readiness check as necessary (e.g. don't wait on CNI DEL)
|
|
if err := readinessCheck(multusShimConfig.MultusSocketDir); err != nil {
|
|
return nil, multusShimConfig.CNIVersion, err
|
|
}
|
|
|
|
cniRequest, err := newCNIRequest(args)
|
|
if err != nil {
|
|
return nil, multusShimConfig.CNIVersion, err
|
|
}
|
|
|
|
var body []byte
|
|
body, err = DoCNI("http://dummy/cni", cniRequest, SocketPath(multusShimConfig.MultusSocketDir))
|
|
if err != nil {
|
|
return nil, multusShimConfig.CNIVersion, fmt.Errorf("%s: StdinData: %s", err.Error(), string(args.StdinData))
|
|
}
|
|
|
|
response := &Response{}
|
|
if len(body) != 0 {
|
|
if err = json.Unmarshal(body, response); err != nil {
|
|
err = fmt.Errorf("failed to unmarshal response '%s': %v", string(body), err)
|
|
return nil, multusShimConfig.CNIVersion, err
|
|
}
|
|
}
|
|
return response, multusShimConfig.CNIVersion, nil
|
|
}
|
|
|
|
// Create and fill a Request with this Plugin's environment and stdin which
|
|
// contain the CNI variables and configuration
|
|
func newCNIRequest(args *skel.CmdArgs) (*Request, error) {
|
|
envMap := make(map[string]string)
|
|
for _, item := range os.Environ() {
|
|
idx := strings.Index(item, "=")
|
|
if idx > 0 {
|
|
envMap[strings.TrimSpace(item[:idx])] = item[idx+1:]
|
|
}
|
|
}
|
|
|
|
return &Request{
|
|
Env: envMap,
|
|
Config: args.StdinData,
|
|
}, nil
|
|
}
|
|
|
|
func shimConfig(cniConfig []byte) (*ShimNetConf, error) {
|
|
multusConfig := &ShimNetConf{}
|
|
if err := json.Unmarshal(cniConfig, multusConfig); err != nil {
|
|
return nil, fmt.Errorf("failed to gather the multus configuration: %w", err)
|
|
}
|
|
if multusConfig.MultusSocketDir == "" {
|
|
multusConfig.MultusSocketDir = defaultMultusRunDir
|
|
}
|
|
// Logging
|
|
logging.SetLogStderr(multusConfig.LogToStderr)
|
|
if multusConfig.LogFile != "" {
|
|
logging.SetLogFile(multusConfig.LogFile)
|
|
}
|
|
if multusConfig.LogLevel != "" {
|
|
logging.SetLogLevel(multusConfig.LogLevel)
|
|
}
|
|
return multusConfig, nil
|
|
}
|