mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	The new flag will parse the `--reserved-memory` flag straight forward to the []kubeletconfig.MemoryReservation variable instead of parsing it to the middle map representation. It gives us possibility to get rid of a lot of unneeded code and use the single presentation for the reserved-memory. Signed-off-by: Artyom Lukianov <alukiano@redhat.com>
		
			
				
	
	
		
			258 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2018 The Kubernetes 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 flag
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"net"
 | 
						|
	"sort"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/spf13/pflag"
 | 
						|
 | 
						|
	v1 "k8s.io/api/core/v1"
 | 
						|
	"k8s.io/apimachinery/pkg/api/resource"
 | 
						|
	utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
						|
	corev1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
 | 
						|
	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
						|
	utilsnet "k8s.io/utils/net"
 | 
						|
)
 | 
						|
 | 
						|
// TODO(mikedanese): remove these flag wrapper types when we remove command line flags
 | 
						|
 | 
						|
var (
 | 
						|
	_ pflag.Value = &IPVar{}
 | 
						|
	_ pflag.Value = &IPPortVar{}
 | 
						|
	_ pflag.Value = &PortRangeVar{}
 | 
						|
	_ pflag.Value = &ReservedMemoryVar{}
 | 
						|
)
 | 
						|
 | 
						|
// IPVar is used for validating a command line option that represents an IP. It implements the pflag.Value interface
 | 
						|
type IPVar struct {
 | 
						|
	Val *string
 | 
						|
}
 | 
						|
 | 
						|
// Set sets the flag value
 | 
						|
func (v IPVar) Set(s string) error {
 | 
						|
	if len(s) == 0 {
 | 
						|
		v.Val = nil
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	if net.ParseIP(s) == nil {
 | 
						|
		return fmt.Errorf("%q is not a valid IP address", s)
 | 
						|
	}
 | 
						|
	if v.Val == nil {
 | 
						|
		// it's okay to panic here since this is programmer error
 | 
						|
		panic("the string pointer passed into IPVar should not be nil")
 | 
						|
	}
 | 
						|
	*v.Val = s
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// String returns the flag value
 | 
						|
func (v IPVar) String() string {
 | 
						|
	if v.Val == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return *v.Val
 | 
						|
}
 | 
						|
 | 
						|
// Type gets the flag type
 | 
						|
func (v IPVar) Type() string {
 | 
						|
	return "ip"
 | 
						|
}
 | 
						|
 | 
						|
// IPPortVar is used for validating a command line option that represents an IP and a port. It implements the pflag.Value interface
 | 
						|
type IPPortVar struct {
 | 
						|
	Val *string
 | 
						|
}
 | 
						|
 | 
						|
// Set sets the flag value
 | 
						|
func (v IPPortVar) Set(s string) error {
 | 
						|
	if len(s) == 0 {
 | 
						|
		v.Val = nil
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	if v.Val == nil {
 | 
						|
		// it's okay to panic here since this is programmer error
 | 
						|
		panic("the string pointer passed into IPPortVar should not be nil")
 | 
						|
	}
 | 
						|
 | 
						|
	// Both IP and IP:port are valid.
 | 
						|
	// Attempt to parse into IP first.
 | 
						|
	if net.ParseIP(s) != nil {
 | 
						|
		*v.Val = s
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	// Can not parse into IP, now assume IP:port.
 | 
						|
	host, port, err := net.SplitHostPort(s)
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("%q is not in a valid format (ip or ip:port): %v", s, err)
 | 
						|
	}
 | 
						|
	if net.ParseIP(host) == nil {
 | 
						|
		return fmt.Errorf("%q is not a valid IP address", host)
 | 
						|
	}
 | 
						|
	if _, err := utilsnet.ParsePort(port, true); err != nil {
 | 
						|
		return fmt.Errorf("%q is not a valid number", port)
 | 
						|
	}
 | 
						|
	*v.Val = s
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// String returns the flag value
 | 
						|
func (v IPPortVar) String() string {
 | 
						|
	if v.Val == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return *v.Val
 | 
						|
}
 | 
						|
 | 
						|
// Type gets the flag type
 | 
						|
func (v IPPortVar) Type() string {
 | 
						|
	return "ipport"
 | 
						|
}
 | 
						|
 | 
						|
// PortRangeVar is used for validating a command line option that represents a port range. It implements the pflag.Value interface
 | 
						|
type PortRangeVar struct {
 | 
						|
	Val *string
 | 
						|
}
 | 
						|
 | 
						|
// Set sets the flag value
 | 
						|
func (v PortRangeVar) Set(s string) error {
 | 
						|
	if _, err := utilnet.ParsePortRange(s); err != nil {
 | 
						|
		return fmt.Errorf("%q is not a valid port range: %v", s, err)
 | 
						|
	}
 | 
						|
	if v.Val == nil {
 | 
						|
		// it's okay to panic here since this is programmer error
 | 
						|
		panic("the string pointer passed into PortRangeVar should not be nil")
 | 
						|
	}
 | 
						|
	*v.Val = s
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// String returns the flag value
 | 
						|
func (v PortRangeVar) String() string {
 | 
						|
	if v.Val == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	return *v.Val
 | 
						|
}
 | 
						|
 | 
						|
// Type gets the flag type
 | 
						|
func (v PortRangeVar) Type() string {
 | 
						|
	return "port-range"
 | 
						|
}
 | 
						|
 | 
						|
// ReservedMemoryVar is used for validating a command line option that represents a reserved memory. It implements the pflag.Value interface
 | 
						|
type ReservedMemoryVar struct {
 | 
						|
	Value       *[]kubeletconfig.MemoryReservation
 | 
						|
	initialized bool // set to true after the first Set call
 | 
						|
}
 | 
						|
 | 
						|
// Set sets the flag value
 | 
						|
func (v *ReservedMemoryVar) Set(s string) error {
 | 
						|
	if v.Value == nil {
 | 
						|
		return fmt.Errorf("no target (nil pointer to *[]MemoryReservation")
 | 
						|
	}
 | 
						|
 | 
						|
	if s == "" {
 | 
						|
		v.Value = nil
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	if !v.initialized || *v.Value == nil {
 | 
						|
		*v.Value = make([]kubeletconfig.MemoryReservation, 0)
 | 
						|
		v.initialized = true
 | 
						|
	}
 | 
						|
 | 
						|
	if s == "" {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	numaNodeReservation := strings.Split(s, ":")
 | 
						|
	if len(numaNodeReservation) != 2 {
 | 
						|
		return fmt.Errorf("the reserved memory has incorrect format, expected numaNodeID:type=quantity[,type=quantity...], got %s", s)
 | 
						|
	}
 | 
						|
 | 
						|
	memoryTypeReservations := strings.Split(numaNodeReservation[1], ",")
 | 
						|
	if len(memoryTypeReservations) < 1 {
 | 
						|
		return fmt.Errorf("the reserved memory has incorrect format, expected numaNodeID:type=quantity[,type=quantity...], got %s", s)
 | 
						|
	}
 | 
						|
 | 
						|
	numaNodeID, err := strconv.Atoi(numaNodeReservation[0])
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("failed to convert the NUMA node ID, exptected integer, got %s", numaNodeReservation[0])
 | 
						|
	}
 | 
						|
 | 
						|
	memoryReservation := kubeletconfig.MemoryReservation{
 | 
						|
		NumaNode: int32(numaNodeID),
 | 
						|
		Limits:   map[v1.ResourceName]resource.Quantity{},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, reservation := range memoryTypeReservations {
 | 
						|
		limit := strings.Split(reservation, "=")
 | 
						|
		if len(limit) != 2 {
 | 
						|
			return fmt.Errorf("the reserved limit has incorrect value, expected type=quantatity, got %s", reservation)
 | 
						|
		}
 | 
						|
 | 
						|
		resourceName := v1.ResourceName(limit[0])
 | 
						|
		if resourceName != v1.ResourceMemory && !corev1helper.IsHugePageResourceName(resourceName) {
 | 
						|
			return fmt.Errorf("memory type conversion error, unknown type: %q", resourceName)
 | 
						|
		}
 | 
						|
 | 
						|
		q, err := resource.ParseQuantity(limit[1])
 | 
						|
		if err != nil {
 | 
						|
			return fmt.Errorf("failed to parse the quantatity, expected quantatity, got %s", limit[1])
 | 
						|
		}
 | 
						|
 | 
						|
		memoryReservation.Limits[v1.ResourceName(limit[0])] = q
 | 
						|
	}
 | 
						|
 | 
						|
	*v.Value = append(*v.Value, memoryReservation)
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// String returns the flag value
 | 
						|
func (v *ReservedMemoryVar) String() string {
 | 
						|
	if v == nil || v.Value == nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
 | 
						|
	var slices []string
 | 
						|
	for _, reservedMemory := range *v.Value {
 | 
						|
		var limits []string
 | 
						|
		for resourceName, q := range reservedMemory.Limits {
 | 
						|
			limits = append(limits, fmt.Sprintf("%s=%s", resourceName, q.String()))
 | 
						|
		}
 | 
						|
 | 
						|
		sort.Strings(limits)
 | 
						|
		slices = append(slices, fmt.Sprintf("%d:%s", reservedMemory.NumaNode, strings.Join(limits, ",")))
 | 
						|
	}
 | 
						|
 | 
						|
	sort.Strings(slices)
 | 
						|
	return strings.Join(slices, ",")
 | 
						|
}
 | 
						|
 | 
						|
// Type gets the flag type
 | 
						|
func (v *ReservedMemoryVar) Type() string {
 | 
						|
	return "reserved-memory"
 | 
						|
}
 |