Skip to content

Commit

Permalink
refactoring to use cloud based GetGroups
Browse files Browse the repository at this point in the history
  • Loading branch information
chrislovecnm committed Sep 29, 2017
1 parent 2f12a3e commit a431eb3
Show file tree
Hide file tree
Showing 16 changed files with 417 additions and 429 deletions.
4 changes: 4 additions & 0 deletions cmd/kops/delete_instancegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ func NewCmdDeleteInstanceGroup(f *util.Factory, out io.Writer) *cobra.Command {
return cmd
}

// RunDeleteInstanceGroup runs the deletion of an instance group
func RunDeleteInstanceGroup(f *util.Factory, out io.Writer, options *DeleteInstanceGroupOptions) error {

// TODO make this drain and validate the ig?
// TODO implement drain and validate logic
groupName := options.GroupName
if groupName == "" {
return fmt.Errorf("GroupName is required")
Expand Down
23 changes: 12 additions & 11 deletions cmd/kops/rollingupdatecluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kops/cmd/kops/util"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/cloudinstances"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/pkg/instancegroups"
"k8s.io/kops/pkg/pretty"
Expand Down Expand Up @@ -274,32 +275,32 @@ func RunRollingUpdateCluster(f *util.Factory, out io.Writer, options *RollingUpd
return err
}

groups, err := instancegroups.FindCloudInstanceGroups(cloud, cluster, instanceGroups, warnUnmatched, nodes)
groups, err := cloud.GetCloudGroups(cluster, instanceGroups, warnUnmatched, nodes)
if err != nil {
return err
}

{
t := &tables.Table{}
t.AddColumn("NAME", func(r *instancegroups.CloudInstanceGroup) string {
t.AddColumn("NAME", func(r *cloudinstances.CloudInstanceGroup) string {
return r.InstanceGroup.ObjectMeta.Name
})
t.AddColumn("STATUS", func(r *instancegroups.CloudInstanceGroup) string {
t.AddColumn("STATUS", func(r *cloudinstances.CloudInstanceGroup) string {
return r.Status
})
t.AddColumn("NEEDUPDATE", func(r *instancegroups.CloudInstanceGroup) string {
t.AddColumn("NEEDUPDATE", func(r *cloudinstances.CloudInstanceGroup) string {
return strconv.Itoa(len(r.NeedUpdate))
})
t.AddColumn("READY", func(r *instancegroups.CloudInstanceGroup) string {
t.AddColumn("READY", func(r *cloudinstances.CloudInstanceGroup) string {
return strconv.Itoa(len(r.Ready))
})
t.AddColumn("MIN", func(r *instancegroups.CloudInstanceGroup) string {
return strconv.Itoa(r.MinSize())
t.AddColumn("MIN", func(r *cloudinstances.CloudInstanceGroup) string {
return strconv.Itoa(r.MinSize)
})
t.AddColumn("MAX", func(r *instancegroups.CloudInstanceGroup) string {
return strconv.Itoa(r.MaxSize())
t.AddColumn("MAX", func(r *cloudinstances.CloudInstanceGroup) string {
return strconv.Itoa(r.MaxSize)
})
t.AddColumn("NODES", func(r *instancegroups.CloudInstanceGroup) string {
t.AddColumn("NODES", func(r *cloudinstances.CloudInstanceGroup) string {
var nodes []*v1.Node
for _, i := range r.Ready {
if i.Node != nil {
Expand All @@ -313,7 +314,7 @@ func RunRollingUpdateCluster(f *util.Factory, out io.Writer, options *RollingUpd
}
return strconv.Itoa(len(nodes))
})
var l []*instancegroups.CloudInstanceGroup
var l []*cloudinstances.CloudInstanceGroup
for _, v := range groups {
l = append(l, v)
}
Expand Down
1 change: 1 addition & 0 deletions hack/.packages
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ k8s.io/kops/pkg/client/clientset_generated/internalclientset/typed/kops/v1alpha2
k8s.io/kops/pkg/client/clientset_generated/internalclientset/typed/kops/v1alpha2/fake
k8s.io/kops/pkg/client/simple
k8s.io/kops/pkg/client/simple/vfsclientset
k8s.io/kops/pkg/cloudinstances
k8s.io/kops/pkg/diff
k8s.io/kops/pkg/dns
k8s.io/kops/pkg/edit
Expand Down
146 changes: 146 additions & 0 deletions pkg/cloudinstances/cloud_instance_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
Copyright 2016 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 cloudinstances

import (
"fmt"

"github.com/golang/glog"
"k8s.io/client-go/pkg/api/v1"
api "k8s.io/kops/pkg/apis/kops"
)

// CloudInstanceGroup is the cloud backing of InstanceGroup.
type CloudInstanceGroup struct {
InstanceGroup *api.InstanceGroup
GroupName string
GroupTemplateName string
Status string
Ready []*CloudInstanceMember
NeedUpdate []*CloudInstanceMember
MinSize int
MaxSize int
}

// CloudInstanceGroupInstance describes an instances in a CloudInstanceGroup group.
type CloudInstanceMember struct {
ID *string
Node *v1.Node
}

// NewCloudInstanceGroup creates a CloudInstanceGroup and validates its initial values.
func NewCloudInstanceGroup(groupName string, groupTemplateName string, ig *api.InstanceGroup, minSize int, maxSize int) (*CloudInstanceGroup, error) {
if groupName == "" {
return nil, fmt.Errorf("group name for cloud instance group must be set")
}
if groupTemplateName == "" {
return nil, fmt.Errorf("group template name for cloud instance group must be set")
}
if ig == nil {
return nil, fmt.Errorf("kops instance group for cloud instance group must be set")
}

if minSize < 0 {
return nil, fmt.Errorf("cloud instance group min size must be zero or greater")
}
if maxSize < 0 {
return nil, fmt.Errorf("cloud instance group max size must be zero or greater")
}

cg := &CloudInstanceGroup{
GroupName: groupName,
GroupTemplateName: groupTemplateName,
InstanceGroup: ig,
MinSize: minSize,
MaxSize: maxSize,
}

return cg, nil
}

// NewCloudInstanceMember creates a new CloudInstanceGroupMember
func (c *CloudInstanceGroup) NewCloudInstanceMember(instanceId *string, newGroupName string, currentGroupName string, nodeMap map[string]*v1.Node) error {
if instanceId == nil {
return fmt.Errorf("instance id for cloud instance member cannot be nil")
}
cm := &CloudInstanceMember{
ID: instanceId,
}
id := *instanceId
node := nodeMap[id]
if node != nil {
cm.Node = node
} else {
glog.V(8).Infof("unable to find node for instance: %s", id)
}

if newGroupName == currentGroupName {
c.Ready = append(c.Ready, cm)
} else {
c.NeedUpdate = append(c.NeedUpdate, cm)
}

return nil
}

// MarkIsReady sets the CloudInstanceGroup status for Ready or NeedsUpdate
func (c *CloudInstanceGroup) MarkIsReady() {
if len(c.NeedUpdate) == 0 {
c.Status = "Ready"
} else {
c.Status = "NeedsUpdate"
}
}

// GetNodeMap returns a list of nodes keyed by there external id
func GetNodeMap(nodes []v1.Node) map[string]*v1.Node {
nodeMap := make(map[string]*v1.Node)
for i := range nodes {
node := &nodes[i]
nodeMap[node.Spec.ExternalID] = node
}

return nodeMap
}

// GetInstanceGroup filters a list of instancegroups for recognized cloud groups
func GetInstanceGroup(name string, clusterName string, instancegroups []*api.InstanceGroup) (*api.InstanceGroup, error) {
var instancegroup *api.InstanceGroup
for _, g := range instancegroups {
var groupName string
switch g.Spec.Role {
case api.InstanceGroupRoleMaster:
groupName = g.ObjectMeta.Name + ".masters." + clusterName
case api.InstanceGroupRoleNode:
groupName = g.ObjectMeta.Name + "." + clusterName
case api.InstanceGroupRoleBastion:
groupName = g.ObjectMeta.Name + "." + clusterName
default:
glog.Warningf("Ignoring InstanceGroup of unknown role %q", g.Spec.Role)
continue
}

if name == groupName {
if instancegroup != nil {
return nil, fmt.Errorf("found multiple instance groups matching ASG %q", groupName)
}
instancegroup = g
}
}

return instancegroup, nil
}
14 changes: 9 additions & 5 deletions pkg/instancegroups/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,32 @@ type DeleteInstanceGroup struct {
Clientset simple.Clientset
}

func (c *DeleteInstanceGroup) DeleteInstanceGroup(group *api.InstanceGroup) error {
groups, err := FindCloudInstanceGroups(c.Cloud, c.Cluster, []*api.InstanceGroup{group}, false, nil)
// DeleteInstanceGroup deletes a cloud instance group
func (d *DeleteInstanceGroup) DeleteInstanceGroup(group *api.InstanceGroup) error {

groups, err := d.Cloud.GetCloudGroups(d.Cluster, []*api.InstanceGroup{group}, false, nil)
if err != nil {
return fmt.Errorf("error finding CloudInstanceGroups: %v", err)
}

// TODO should we drain nodes and validate the cluster?
cig := groups[group.ObjectMeta.Name]
if cig == nil {
glog.Warningf("AutoScalingGroup %q not found in cloud - skipping delete", group.ObjectMeta.Name)
} else {
if len(groups) != 1 {
return fmt.Errorf("Multiple InstanceGroup resources found in cloud")
return fmt.Errorf("multiple InstanceGroup resources found in cloud")
}

glog.Infof("Deleting AutoScalingGroup %q", group.ObjectMeta.Name)

err = cig.Delete(c.Cloud)
err = d.Cloud.DeleteGroup(cig.GroupName, cig.GroupTemplateName)
if err != nil {
return fmt.Errorf("error deleting cloud resources for InstanceGroup: %v", err)
}
}

err = c.Clientset.InstanceGroupsFor(c.Cluster).Delete(group.ObjectMeta.Name, nil)
err = d.Clientset.InstanceGroupsFor(d.Cluster).Delete(group.ObjectMeta.Name, nil)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit a431eb3

Please sign in to comment.