diff --git a/cluster-autoscaler/cloudprovider/aws/aws_cloud_provider.go b/cluster-autoscaler/cloudprovider/aws/aws_cloud_provider.go index 457ac68954..be9de9f6c3 100644 --- a/cluster-autoscaler/cloudprovider/aws/aws_cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/aws/aws_cloud_provider.go @@ -198,6 +198,11 @@ func (asg *Asg) Debug() string { return fmt.Sprintf("%s (%d:%d)", asg.Id(), asg.MinSize(), asg.MaxSize()) } +// Nodes returns a list of all nodes that belong to this node group. +func (asg *Asg) Nodes() ([]string, error) { + return asg.awsManager.GetAsgNodes(asg) +} + func buildAsg(value string, awsManager *AwsManager) (*Asg, error) { tokens := strings.SplitN(value, ":", 3) if len(tokens) != 3 { diff --git a/cluster-autoscaler/cloudprovider/aws/aws_manager.go b/cluster-autoscaler/cloudprovider/aws/aws_manager.go index c2c25f1e19..efe9086a0f 100644 --- a/cluster-autoscaler/cloudprovider/aws/aws_manager.go +++ b/cluster-autoscaler/cloudprovider/aws/aws_manager.go @@ -185,20 +185,10 @@ func (m *AwsManager) regenerateCache() error { for _, asg := range m.asgs { glog.V(4).Infof("Regenerating ASG information for %s", asg.config.Name) - params := &autoscaling.DescribeAutoScalingGroupsInput{ - AutoScalingGroupNames: []*string{aws.String(asg.config.Name)}, - MaxRecords: aws.Int64(1), - } - groups, err := m.service.DescribeAutoScalingGroups(params) + group, err := m.getAutoscalingGroup(asg.config.Name) if err != nil { - glog.V(4).Infof("Failed ASG info request for %s: %v", asg.config.Name, err) return err } - if len(groups.AutoScalingGroups) < 1 { - return fmt.Errorf("Unable to get first autoscaling.Group for %s", asg.config.Name) - } - group := *groups.AutoScalingGroups[0] - for _, instance := range group.Instances { ref := AwsRef{Name: *instance.InstanceId} newCache[ref] = asg.config @@ -208,3 +198,32 @@ func (m *AwsManager) regenerateCache() error { m.asgCache = newCache return nil } + +func (m *AwsManager) getAutoscalingGroup(name string) (*autoscaling.Group, error) { + params := &autoscaling.DescribeAutoScalingGroupsInput{ + AutoScalingGroupNames: []*string{aws.String(name)}, + MaxRecords: aws.Int64(1), + } + groups, err := m.service.DescribeAutoScalingGroups(params) + if err != nil { + glog.V(4).Infof("Failed ASG info request for %s: %v", name, err) + return nil, err + } + if len(groups.AutoScalingGroups) < 1 { + return nil, fmt.Errorf("Unable to get first autoscaling.Group for %s", name) + } + return groups.AutoScalingGroups[0], nil +} + +// GetAsgNodes returns Asg nodes. +func (m *AwsManager) GetAsgNodes(asg *Asg) ([]string, error) { + result := make([]string, 0) + group, err := m.getAutoscalingGroup(asg.Name) + if err != nil { + return []string{}, err + } + for _, instance := range group.Instances { + result = append(result, *instance.InstanceId) + } + return result, nil +} diff --git a/cluster-autoscaler/cloudprovider/cloud_provider.go b/cluster-autoscaler/cloudprovider/cloud_provider.go index 32136342ea..8b6274c135 100644 --- a/cluster-autoscaler/cloudprovider/cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/cloud_provider.go @@ -65,4 +65,7 @@ type NodeGroup interface { // Debug returns a string containing all information regarding this node group. Debug() string + + // Nodes returns a list of all nodes that belong to this node group. + Nodes() ([]string, error) } diff --git a/cluster-autoscaler/cloudprovider/gce/gce_cloud_provider.go b/cluster-autoscaler/cloudprovider/gce/gce_cloud_provider.go index 006bc43f44..039223d9dc 100644 --- a/cluster-autoscaler/cloudprovider/gce/gce_cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/gce/gce_cloud_provider.go @@ -203,6 +203,11 @@ func (mig *Mig) Debug() string { return fmt.Sprintf("%s (%d:%d)", mig.Id(), mig.MinSize(), mig.MaxSize()) } +// Nodes returns a list of all nodes that belong to this node group. +func (mig *Mig) Nodes() ([]string, error) { + return mig.gceManager.GetMigNodes(mig) +} + func buildMig(value string, gceManager *GceManager) (*Mig, error) { tokens := strings.SplitN(value, ":", 3) if len(tokens) != 3 { diff --git a/cluster-autoscaler/cloudprovider/gce/gce_manager.go b/cluster-autoscaler/cloudprovider/gce/gce_manager.go index a2cb61d102..edb5845a09 100644 --- a/cluster-autoscaler/cloudprovider/gce/gce_manager.go +++ b/cluster-autoscaler/cloudprovider/gce/gce_manager.go @@ -230,3 +230,20 @@ func (m *GceManager) regenerateCache() error { m.migCache = newMigCache return nil } + +// GetMigNodes returns mig nodes. +func (m *GceManager) GetMigNodes(mig *Mig) ([]string, error) { + instances, err := m.service.InstanceGroupManagers.ListManagedInstances(mig.Project, mig.Zone, mig.Name).Do() + if err != nil { + return []string{}, err + } + result := make([]string, 0) + for _, instance := range instances.ManagedInstances { + _, _, name, err := ParseInstanceUrl(instance.Instance) + if err != nil { + return []string{}, err + } + result = append(result, name) + } + return result, nil +} diff --git a/cluster-autoscaler/cloudprovider/test/test_cloud_provider.go b/cluster-autoscaler/cloudprovider/test/test_cloud_provider.go index 3122018fb9..16baa18ecd 100644 --- a/cluster-autoscaler/cloudprovider/test/test_cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/test/test_cloud_provider.go @@ -186,3 +186,17 @@ func (tng *TestNodeGroup) Debug() string { return fmt.Sprintf("%s target:%d min:%d max:%d", tng.id, tng.targetSize, tng.minSize, tng.maxSize) } + +// Nodes returns a list of all nodes that belong to this node group. +func (tng *TestNodeGroup) Nodes() ([]string, error) { + tng.Lock() + defer tng.Unlock() + + result := make([]string, 0) + for node, nodegroup := range tng.cloudProvider.nodes { + if nodegroup == tng.id { + result = append(result, node) + } + } + return result, nil +} diff --git a/cluster-autoscaler/expander/waste/waste_test.go b/cluster-autoscaler/expander/waste/waste_test.go index 58b61191a4..02ab580ec1 100644 --- a/cluster-autoscaler/expander/waste/waste_test.go +++ b/cluster-autoscaler/expander/waste/waste_test.go @@ -37,6 +37,7 @@ func (f *FakeNodeGroup) IncreaseSize(delta int) error { return nil } func (f *FakeNodeGroup) DeleteNodes([]*apiv1.Node) error { return nil } func (f *FakeNodeGroup) Id() string { return f.id } func (f *FakeNodeGroup) Debug() string { return f.id } +func (f *FakeNodeGroup) Nodes() ([]string, error) { return []string{}, nil } func makeNodeInfo(cpu int64, memory int64, pods int64) *schedulercache.NodeInfo { node := &apiv1.Node{