diff --git a/aws.go b/aws.go index 5ef692f..0534d7a 100644 --- a/aws.go +++ b/aws.go @@ -55,31 +55,6 @@ func getIdToCLBs(svc elbiface.ELBAPI, ids []string) (map[string][]string, error) return idToCLBs, nil } -func getIdToASGs(svc autoscalingiface.AutoScalingAPI, ids []string) (map[string][]string, error) { - if len(ids) == 0 { - return nil, nil - } - - ec2input := &autoscaling.DescribeAutoScalingInstancesInput{ - InstanceIds: aws.StringSlice(ids), - } - nodesResult, err := svc.DescribeAutoScalingInstances(ec2input) - if err != nil { - return nil, fmt.Errorf("Unable to get description for node %v: %v", ids, err) - } - if len(nodesResult.AutoScalingInstances) < 1 { - return nil, fmt.Errorf("Did not get any autoscaling instances for %v", ids) - } - - idToASGs := map[string][]string{} - - for _, i := range nodesResult.AutoScalingInstances { - idToASGs[*i.InstanceId] = append(idToASGs[*i.InstanceId], *i.AutoScalingGroupName) - } - - return idToASGs, nil -} - func getIdToTGs(svc elbv2iface.ELBV2API, ids []string) (map[string][]string, map[string]map[string][]elbv2.TargetDescription, error) { if len(ids) == 0 { return nil, nil, nil @@ -136,37 +111,6 @@ func getIdToTGs(svc elbv2iface.ELBV2API, ids []string) (map[string][]string, map return idToTGs, idToTDs, nil } -func detachInstancesFromASGs(svc autoscalingiface.AutoScalingAPI, asgName string, instanceIDs []string) error { - input := &autoscaling.DetachInstancesInput{ - AutoScalingGroupName: aws.String(asgName), - InstanceIds: aws.StringSlice(instanceIDs), - // On manual drain we should probably keep the desired capacity unchanged(hence this should be set to `false`), - // but for automated drains like done by Cluster Autoscaler, we should decrement it as the number of desired instances is managed by CA - // - // We opts to let admins handle manual drain cases on their own. - ShouldDecrementDesiredCapacity: aws.Bool(true), - } - - // See https://docs.aws.amazon.com/autoscaling/ec2/APIReference/API_DetachInstances.html for the API spec - _, err := svc.DetachInstances(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - - switch aerr.Code() { - case autoscaling.ErrCodeResourceContentionFault: - return fmt.Errorf("Could not detach instances, any resource is in contention, will try in next loop") - default: - return fmt.Errorf("Unknown aws error when detaching instances: %v", aerr.Error()) - } - } else { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - return fmt.Errorf("Unknown non-aws error when terminating old instance: %v", err.Error()) - } - } - return nil -} - func registerInstancesToCLBs(svc elbiface.ELBAPI, lbName string, instanceIDs []string) error { instances := []*elb.Instance{} diff --git a/aws_test.go b/aws_test.go deleted file mode 100644 index 882d5bb..0000000 --- a/aws_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import ( - "github.com/aws/aws-sdk-go/service/elb/elbiface" - "github.com/aws/aws-sdk-go/service/elbv2/elbv2iface" - "testing" - - "github.com/aws/aws-sdk-go/service/autoscaling" - "github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface" -) - -type mockElbSvc struct { - elbiface.ELBAPI - err error - counter funcCounter -} - -type mockELbV2Svc struct { - elbv2iface.ELBV2API - err error - counter funcCounter -} - -type mockAsgSvc struct { - autoscalingiface.AutoScalingAPI - err error - counter funcCounter - groups map[string]*autoscaling.Group -} - -func (m *mockAsgSvc) TerminateInstanceInAutoScalingGroup(in *autoscaling.TerminateInstanceInAutoScalingGroupInput) (*autoscaling.TerminateInstanceInAutoScalingGroupOutput, error) { - m.counter.add("TerminateInstanceInAutoScalingGroup", in) - ret := &autoscaling.TerminateInstanceInAutoScalingGroupOutput{} - return ret, m.err -} -func (m *mockAsgSvc) DescribeAutoScalingGroups(in *autoscaling.DescribeAutoScalingGroupsInput) (*autoscaling.DescribeAutoScalingGroupsOutput, error) { - m.counter.add("DescribeAutoScalingGroups", in) - groups := make([]*autoscaling.Group, 0) - for _, n := range in.AutoScalingGroupNames { - if group, ok := m.groups[*n]; ok { - groups = append(groups, group) - } - } - return &autoscaling.DescribeAutoScalingGroupsOutput{ - AutoScalingGroups: groups, - }, m.err -} -func (m *mockAsgSvc) SetDesiredCapacity(in *autoscaling.SetDesiredCapacityInput) (*autoscaling.SetDesiredCapacityOutput, error) { - m.counter.add("SetDesiredCapacity", in) - ret := &autoscaling.SetDesiredCapacityOutput{} - return ret, m.err -} - -func TestAwsGetServices(t *testing.T) { - asg, elb, elbv2, err := awsGetServices() - if err != nil { - t.Fatalf("Unexpected err %v", err) - } - if asg == nil { - t.Fatalf("asg unexpectedly nil") - } - if elb == nil { - t.Fatalf("elb unexpectedly nil") - } - if elbv2 == nil { - t.Fatalf("elbv2 unexpectedly nil") - } -} diff --git a/cache.go b/cache.go index 4709b4d..1ccddee 100644 --- a/cache.go +++ b/cache.go @@ -177,14 +177,3 @@ func (n *NodeAttachments) cacheNodeAttachments(nodes []corev1.Node) error { return nil } - -type TargetGroupReference struct { - // AccountID is AWS Account's ID - AccountID int - // Region is the AWS region to use - Region string -} - -const ( - TargetGroupReferenceResourceIDSeparator = "." -) diff --git a/detach.go b/detach.go index 75c88b1..144e6a0 100644 --- a/detach.go +++ b/detach.go @@ -7,18 +7,6 @@ import ( "k8s.io/apimachinery/pkg/types" ) -const ( - LabelValueAttached = "attached" - LabelValueDetached = "detached" - - healthy = "Healthy" -) - -// deprecatedDetachUnschedulables runs a set of EC2 instance detachments in the loop to update ASGs to not manage unschedulable K8s nodes -func (n *NodeAttachments) deprecatedDetachUnschedulables() error { - return nil -} - func (n *NodeAttachments) detachNodes(unschedulableNodes []corev1.Node) (bool, error) { var processed int diff --git a/kubernetes.go b/kubernetes.go index 44d38a9..0572fc5 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -2,105 +2,9 @@ package main import ( "fmt" - "log" - "os" - "path/filepath" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" ) -type KubernetesService interface { - getUnschedulableNodes() ([]corev1.Node, error) -} - -type kubernetesSvc struct { - clientset *kubernetes.Clientset - ignoreDaemonSets bool - deleteLocalData bool -} - -func kubeGetClientset() (*kubernetes.Clientset, error) { - config, err := rest.InClusterConfig() - if err != nil { - if err == rest.ErrNotInCluster { - config, err = getKubeOutOfCluster() - if err != nil { - return nil, err - } - } else { - return nil, fmt.Errorf("Error getting kubernetes config from within cluster") - } - } - - clientset, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - return clientset, nil -} - -func getKubeOutOfCluster() (*rest.Config, error) { - kubeconfig := os.Getenv("KUBECONFIG") - if kubeconfig == "" { - if home := homeDir(); home != "" { - kubeconfig = filepath.Join(home, ".kube", "config") - } else { - return nil, fmt.Errorf("Not KUBECONFIG provided and no home available") - } - } - - // use the current context in kubeconfig - config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) - if err != nil { - panic(err.Error()) - } - return config, nil -} - -func homeDir() string { - if h := os.Getenv("HOME"); h != "" { - return h - } - return os.Getenv("USERPROFILE") // windows -} - -func createK8sService() (KubernetesService, error) { - clientset, err := kubeGetClientset() - if err != nil { - log.Fatalf("Error getting kubernetes connection: %v", err) - } - if clientset == nil { - return nil, nil - } - return &kubernetesSvc{clientset: clientset}, nil -} - -func (svc *kubernetesSvc) getUnschedulableNodes() ([]corev1.Node, error) { - if svc.clientset == nil { - return nil, nil - } - - nodeList, err := svc.clientset.CoreV1().Nodes().List(v1.ListOptions{}) - if err != nil { - return nil, fmt.Errorf("Unexpected error getting kubernetes nodes: %v", err) - } - - var unschedulables []corev1.Node - - for _, node := range nodeList.Items { - if isUnschedulable(node) { - unschedulables = append(unschedulables, node) - } - } - - return unschedulables, nil -} - func getInstanceID(node corev1.Node) (string, error) { labels := node.GetLabels() @@ -111,7 +15,3 @@ func getInstanceID(node corev1.Node) (string, error) { return instanceID, nil } - -func isUnschedulable(node corev1.Node) bool { - return node.Spec.Unschedulable -} diff --git a/log_level.go b/log_level.go index 1852fd5..7ec26fa 100644 --- a/log_level.go +++ b/log_level.go @@ -6,8 +6,6 @@ import ( "go.uber.org/zap/zapcore" ) -var DefaultLogLevel = "info" - func stringToZapLogLevel(lvl string) zapcore.Level { switch lvl { case "debug": diff --git a/main.go b/main.go index 79b8a38..7d31412 100644 --- a/main.go +++ b/main.go @@ -61,8 +61,13 @@ func main() { // log: exiting because of error: log: cannot create log: open /tmp/manager.controller-manager-5f7bd48566-mzkgz.unknownuser.log.INFO.20200309-120154.1: no such file or directory klogFlags := flag.NewFlagSet("klog", flag.ContinueOnError) klog.InitFlags(klogFlags) - klogFlags.Set("logtostderr", "true") - klogFlags.Parse([]string{}) + if err := klogFlags.Set("logtostderr", "true"); err != nil { + panic(err) + } + + if err := klogFlags.Parse([]string{}); err != nil { + panic(err) + } var ( syncPeriod time.Duration diff --git a/node_controller_test.go b/node_controller_test.go index d267ab6..81276ca 100644 --- a/node_controller_test.go +++ b/node_controller_test.go @@ -76,6 +76,7 @@ func randStringRunes(n int) string { var _ = Context("Inside of a new namespace", func() { ctx := context.TODO() + _ = SetupTest(ctx) Describe("when no existing resources exist", func() { diff --git a/util_test.go b/util_test.go deleted file mode 100644 index 3d989d9..0000000 --- a/util_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -func testStringInt64MapEq(a, b map[string]int64) bool { - if len(a) != len(b) { - return false - } - for k, v := range a { - vb, ok := b[k] - if !ok { - return false - } - if vb != v { - return false - } - } - return true -} - -type funcCounter struct { - count []funcCounterImpl -} -type funcCounterImpl struct { - name string - params []interface{} -} - -func (f *funcCounter) add(name string, params ...interface{}) { - f.count = append(f.count, funcCounterImpl{ - name: name, - params: params, - }) -} -func (f *funcCounter) last() (string, []interface{}) { //nolint:unused - l := len(f.count) - if l > 0 { - return f.count[l-1].name, f.count[l-1].params - } - return "", nil -} -func (f *funcCounter) lastByName(name string) []interface{} { //nolint:unused - var params []interface{} - for _, call := range f.count { - if call.name == name { - params = call.params - } - } - return params -} -func (f *funcCounter) filterByName(name string) []funcCounterImpl { - ret := make([]funcCounterImpl, 0) - for _, call := range f.count { - if call.name == name { - ret = append(ret, call) - } - } - return ret -}