Merge pull request #8491 from gvnc/oci-auto-discovery-enhancement
read min and max values from nodepool tags for oci autodiscovery
This commit is contained in:
		
						commit
						bf86702ba8
					
				| 
						 | 
					@ -40,6 +40,8 @@ const (
 | 
				
			||||||
	nodepoolTags          = "nodepoolTags"
 | 
						nodepoolTags          = "nodepoolTags"
 | 
				
			||||||
	min                   = "min"
 | 
						min                   = "min"
 | 
				
			||||||
	max                   = "max"
 | 
						max                   = "max"
 | 
				
			||||||
 | 
						minSize               = "minSize"
 | 
				
			||||||
 | 
						maxSize               = "maxSize"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
| 
						 | 
					@ -90,6 +92,9 @@ func CreateNodePoolManager(cloudConfigPath string, nodeGroupAutoDiscoveryList []
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	var configProvider common.ConfigurationProvider
 | 
						var configProvider common.ConfigurationProvider
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// enable SDK to look up the IMDS endpoint to figure out the right realmDomain
 | 
				
			||||||
 | 
						common.EnableInstanceMetadataServiceLookup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if os.Getenv(ipconsts.OciUseWorkloadIdentityEnvVar) == "true" {
 | 
						if os.Getenv(ipconsts.OciUseWorkloadIdentityEnvVar) == "true" {
 | 
				
			||||||
		klog.Info("using workload identity provider")
 | 
							klog.Info("using workload identity provider")
 | 
				
			||||||
		configProvider, err = auth.OkeWorkloadIdentityConfigurationProvider()
 | 
							configProvider, err = auth.OkeWorkloadIdentityConfigurationProvider()
 | 
				
			||||||
| 
						 | 
					@ -214,14 +219,15 @@ func autoDiscoverNodeGroups(m *ociManagerImpl, okeClient okeClient, nodeGroup no
 | 
				
			||||||
		if validateNodepoolTags(nodeGroup.tags, nodePoolSummary.FreeformTags, nodePoolSummary.DefinedTags) {
 | 
							if validateNodepoolTags(nodeGroup.tags, nodePoolSummary.FreeformTags, nodePoolSummary.DefinedTags) {
 | 
				
			||||||
			nodepool := &nodePool{}
 | 
								nodepool := &nodePool{}
 | 
				
			||||||
			nodepool.id = *nodePoolSummary.Id
 | 
								nodepool.id = *nodePoolSummary.Id
 | 
				
			||||||
			nodepool.minSize = nodeGroup.minSize
 | 
								// set minSize-maxSize from nodepool free form tags, or else use nodeGroupAutoDiscovery configuration
 | 
				
			||||||
			nodepool.maxSize = nodeGroup.maxSize
 | 
								nodepool.minSize = getIntFromMap(nodePoolSummary.FreeformTags, minSize, nodeGroup.minSize)
 | 
				
			||||||
 | 
								nodepool.maxSize = getIntFromMap(nodePoolSummary.FreeformTags, maxSize, nodeGroup.maxSize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			nodepool.manager = nodeGroup.manager
 | 
								nodepool.manager = nodeGroup.manager
 | 
				
			||||||
			nodepool.kubeClient = nodeGroup.kubeClient
 | 
								nodepool.kubeClient = nodeGroup.kubeClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			m.staticNodePools[nodepool.id] = nodepool
 | 
								m.staticNodePools[nodepool.id] = nodepool
 | 
				
			||||||
			klog.V(5).Infof("auto discovered nodepool in compartment : %s , nodepoolid: %s", nodeGroup.compartmentId, nodepool.id)
 | 
								klog.V(4).Infof("auto discovered nodepool in compartment : %s , nodepoolid: %s ,minSize: %d, maxSize:%d", nodeGroup.compartmentId, nodepool.id, nodepool.minSize, nodepool.maxSize)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			klog.Warningf("nodepool ignored as the tags do not satisfy the requirement : %s , %v, %v", *nodePoolSummary.Id, nodePoolSummary.FreeformTags, nodePoolSummary.DefinedTags)
 | 
								klog.Warningf("nodepool ignored as the tags do not satisfy the requirement : %s , %v, %v", *nodePoolSummary.Id, nodePoolSummary.FreeformTags, nodePoolSummary.DefinedTags)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -229,6 +235,18 @@ func autoDiscoverNodeGroups(m *ociManagerImpl, okeClient okeClient, nodeGroup no
 | 
				
			||||||
	return true, nil
 | 
						return true, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getIntFromMap(m map[string]string, key string, defaultValue int) int {
 | 
				
			||||||
 | 
						value, ok := m[key]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return defaultValue
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						i, err := strconv.Atoi(value)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return defaultValue
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return i
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func validateNodepoolTags(nodeGroupTags map[string]string, freeFormTags map[string]string, definedTags map[string]map[string]interface{}) bool {
 | 
					func validateNodepoolTags(nodeGroupTags map[string]string, freeFormTags map[string]string, definedTags map[string]map[string]interface{}) bool {
 | 
				
			||||||
	if nodeGroupTags != nil {
 | 
						if nodeGroupTags != nil {
 | 
				
			||||||
		for tagKey, tagValue := range nodeGroupTags {
 | 
							for tagKey, tagValue := range nodeGroupTags {
 | 
				
			||||||
| 
						 | 
					@ -394,11 +412,35 @@ func (m *ociManagerImpl) TaintToPreventFurtherSchedulingOnRestart(nodes []*apiv1
 | 
				
			||||||
func (m *ociManagerImpl) forceRefresh() error {
 | 
					func (m *ociManagerImpl) forceRefresh() error {
 | 
				
			||||||
	// auto discover node groups
 | 
						// auto discover node groups
 | 
				
			||||||
	if m.nodeGroups != nil {
 | 
						if m.nodeGroups != nil {
 | 
				
			||||||
		// empty previous nodepool map to do an auto discovery
 | 
							// create a copy of m.staticNodePools to use it in comparison
 | 
				
			||||||
 | 
							staticNodePoolsCopy := make(map[string]NodePool)
 | 
				
			||||||
 | 
							for k, v := range m.staticNodePools {
 | 
				
			||||||
 | 
								staticNodePoolsCopy[k] = v
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// empty previous nodepool map to do a fresh auto discovery
 | 
				
			||||||
		m.staticNodePools = make(map[string]NodePool)
 | 
							m.staticNodePools = make(map[string]NodePool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// run auto-discovery
 | 
				
			||||||
		for _, nodeGroup := range m.nodeGroups {
 | 
							for _, nodeGroup := range m.nodeGroups {
 | 
				
			||||||
			autoDiscoverNodeGroups(m, m.okeClient, nodeGroup)
 | 
								autoDiscoverNodeGroups(m, m.okeClient, nodeGroup)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// compare the new and previous nodepool list to log the updates
 | 
				
			||||||
 | 
							for nodepoolId, nodepool := range m.staticNodePools {
 | 
				
			||||||
 | 
								if _, ok := staticNodePoolsCopy[nodepoolId]; !ok {
 | 
				
			||||||
 | 
									klog.Infof("New nodepool discovered. [id: %s ,minSize: %d, maxSize:%d]", nodepool.Id(), nodepool.MinSize(), nodepool.MaxSize())
 | 
				
			||||||
 | 
								} else if staticNodePoolsCopy[nodepoolId].MinSize() != nodepool.MinSize() || staticNodePoolsCopy[nodepoolId].MaxSize() != nodepool.MaxSize() {
 | 
				
			||||||
 | 
									klog.Infof("Nodepool min/max sizes are updated. [id: %s ,minSize: %d, maxSize:%d]", nodepool.Id(), nodepool.MinSize(), nodepool.MaxSize())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// log if there are nodepools removed from the list
 | 
				
			||||||
 | 
							for k := range staticNodePoolsCopy {
 | 
				
			||||||
 | 
								if _, ok := m.staticNodePools[k]; !ok {
 | 
				
			||||||
 | 
									klog.Infof("Previously auto-discovered nodepool removed from the managed nodepool list. nodepoolid: %s", k)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// rebuild nodepool cache
 | 
						// rebuild nodepool cache
 | 
				
			||||||
	err := m.nodePoolCache.rebuild(m.staticNodePools, maxGetNodepoolRetries)
 | 
						err := m.nodePoolCache.rebuild(m.staticNodePools, maxGetNodepoolRetries)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,10 +6,12 @@ package nodepools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/nodepools/consts"
 | 
						"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/nodepools/consts"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiv1 "k8s.io/api/core/v1"
 | 
						apiv1 "k8s.io/api/core/v1"
 | 
				
			||||||
	"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
 | 
						"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
 | 
				
			||||||
| 
						 | 
					@ -20,6 +22,10 @@ import (
 | 
				
			||||||
	oke "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/vendor-internal/github.com/oracle/oci-go-sdk/v65/containerengine"
 | 
						oke "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/vendor-internal/github.com/oracle/oci-go-sdk/v65/containerengine"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						autoDiscoveryCompartment = "ocid1.compartment.oc1.test-region.test"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNodePoolFromArgs(t *testing.T) {
 | 
					func TestNodePoolFromArgs(t *testing.T) {
 | 
				
			||||||
	value := `1:5:ocid`
 | 
						value := `1:5:ocid`
 | 
				
			||||||
	nodePool, err := nodePoolFromArg(value)
 | 
						nodePool, err := nodePoolFromArg(value)
 | 
				
			||||||
| 
						 | 
					@ -321,8 +327,15 @@ func TestBuildGenericLabels(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type mockOKEClient struct{}
 | 
					type mockOKEClient struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c mockOKEClient) GetNodePool(context.Context, oke.GetNodePoolRequest) (oke.GetNodePoolResponse, error) {
 | 
					func (c mockOKEClient) GetNodePool(ctx context.Context, req oke.GetNodePoolRequest) (oke.GetNodePoolResponse, error) {
 | 
				
			||||||
	return oke.GetNodePoolResponse{}, nil
 | 
						return oke.GetNodePoolResponse{
 | 
				
			||||||
 | 
							NodePool: oke.NodePool{
 | 
				
			||||||
 | 
								Id: req.NodePoolId,
 | 
				
			||||||
 | 
								NodeConfigDetails: &oke.NodePoolNodeConfigDetails{
 | 
				
			||||||
 | 
									Size: common.Int(1),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (c mockOKEClient) UpdateNodePool(context.Context, oke.UpdateNodePoolRequest) (oke.UpdateNodePoolResponse, error) {
 | 
					func (c mockOKEClient) UpdateNodePool(context.Context, oke.UpdateNodePoolRequest) (oke.UpdateNodePoolResponse, error) {
 | 
				
			||||||
	return oke.UpdateNodePoolResponse{}, nil
 | 
						return oke.UpdateNodePoolResponse{}, nil
 | 
				
			||||||
| 
						 | 
					@ -336,7 +349,39 @@ func (c mockOKEClient) DeleteNode(context.Context, oke.DeleteNodeRequest) (oke.D
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c mockOKEClient) ListNodePools(context.Context, oke.ListNodePoolsRequest) (oke.ListNodePoolsResponse, error) {
 | 
					func (c mockOKEClient) ListNodePools(ctx context.Context, req oke.ListNodePoolsRequest) (oke.ListNodePoolsResponse, error) {
 | 
				
			||||||
 | 
						// below test data added for auto-discovery tests
 | 
				
			||||||
 | 
						if req.CompartmentId != nil && *req.CompartmentId == autoDiscoveryCompartment {
 | 
				
			||||||
 | 
							freeformTags1 := map[string]string{
 | 
				
			||||||
 | 
								"ca-managed": "true",
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							freeformTags2 := map[string]string{
 | 
				
			||||||
 | 
								"ca-managed": "true",
 | 
				
			||||||
 | 
								"minSize":    "4",
 | 
				
			||||||
 | 
								"maxSize":    "10",
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							definedTags := map[string]map[string]interface{}{
 | 
				
			||||||
 | 
								"namespace": {
 | 
				
			||||||
 | 
									"foo": "bar",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							resp := oke.ListNodePoolsResponse{
 | 
				
			||||||
 | 
								Items: []oke.NodePoolSummary{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Id:           common.String("node-pool-1"),
 | 
				
			||||||
 | 
										FreeformTags: freeformTags1,
 | 
				
			||||||
 | 
										DefinedTags:  definedTags,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Id:           common.String("node-pool-2"),
 | 
				
			||||||
 | 
										FreeformTags: freeformTags2,
 | 
				
			||||||
 | 
										DefinedTags:  definedTags,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return resp, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return oke.ListNodePoolsResponse{}, nil
 | 
						return oke.ListNodePoolsResponse{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -393,8 +438,41 @@ func TestRemoveInstance(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNodeGroupAutoDiscovery(t *testing.T) {
 | 
				
			||||||
 | 
						var nodeGroupArg = fmt.Sprintf("clusterId:ocid1.cluster.oc1.test-region.test,compartmentId:%s,nodepoolTags:ca-managed=true&namespace.foo=bar,min:1,max:5", autoDiscoveryCompartment)
 | 
				
			||||||
 | 
						nodeGroup, err := nodeGroupFromArg(nodeGroupArg)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Error: #{err}")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						nodePoolCache := newNodePoolCache(nil)
 | 
				
			||||||
 | 
						nodePoolCache.okeClient = mockOKEClient{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cloudConfig := &ocicommon.CloudConfig{}
 | 
				
			||||||
 | 
						cloudConfig.Global.RefreshInterval = 5 * time.Minute
 | 
				
			||||||
 | 
						cloudConfig.Global.CompartmentID = autoDiscoveryCompartment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager := &ociManagerImpl{
 | 
				
			||||||
 | 
							nodePoolCache:   nodePoolCache,
 | 
				
			||||||
 | 
							nodeGroups:      []nodeGroupAutoDiscovery{*nodeGroup},
 | 
				
			||||||
 | 
							okeClient:       mockOKEClient{},
 | 
				
			||||||
 | 
							cfg:             cloudConfig,
 | 
				
			||||||
 | 
							staticNodePools: map[string]NodePool{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// test data to use as initial nodepools
 | 
				
			||||||
 | 
						nodepool2 := &nodePool{
 | 
				
			||||||
 | 
							id: "node-pool-2", minSize: 1, maxSize: 5,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						manager.staticNodePools[nodepool2.id] = nodepool2
 | 
				
			||||||
 | 
						nodepool3 := &nodePool{
 | 
				
			||||||
 | 
							id: "node-pool-3", minSize: 2, maxSize: 5,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						manager.staticNodePools[nodepool3.id] = nodepool3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager.forceRefresh()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNodeGroupFromArg(t *testing.T) {
 | 
					func TestNodeGroupFromArg(t *testing.T) {
 | 
				
			||||||
	var nodeGroupArg = "clusterId:ocid1.cluster.oc1.test-region.test,compartmentId:ocid1.compartment.oc1.test-region.test,nodepoolTags:ca-managed=true&namespace.foo=bar,min:1,max:5"
 | 
						var nodeGroupArg = fmt.Sprintf("clusterId:ocid1.cluster.oc1.test-region.test,compartmentId:%s,nodepoolTags:ca-managed=true&namespace.foo=bar,min:1,max:5", autoDiscoveryCompartment)
 | 
				
			||||||
	nodeGroupAutoDiscovery, err := nodeGroupFromArg(nodeGroupArg)
 | 
						nodeGroupAutoDiscovery, err := nodeGroupFromArg(nodeGroupArg)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Errorf("Error: #{err}")
 | 
							t.Errorf("Error: #{err}")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue