upup: More delete cleanup, use statestore by default

This commit is contained in:
Justin Santa Barbara 2016-06-28 11:47:19 -04:00
parent 8e52111c0f
commit e315564cfa
2 changed files with 204 additions and 104 deletions

View File

@ -6,7 +6,9 @@ import (
"bytes"
"github.com/golang/glog"
"github.com/spf13/cobra"
"k8s.io/kube-deploy/upup/pkg/api"
"k8s.io/kube-deploy/upup/pkg/fi"
"k8s.io/kube-deploy/upup/pkg/fi/cloudup"
"k8s.io/kube-deploy/upup/pkg/fi/cloudup/awsup"
"k8s.io/kube-deploy/upup/pkg/kutil"
"os"
@ -17,6 +19,7 @@ import (
type DeleteClusterCmd struct {
Yes bool
Region string
External bool
}
var deleteCluster DeleteClusterCmd
@ -38,30 +41,59 @@ func init() {
cmd.Flags().BoolVar(&deleteCluster.Yes, "yes", false, "Delete without confirmation")
cmd.Flags().BoolVar(&deleteCluster.External, "external", false, "Delete an external cluster")
cmd.Flags().StringVar(&deleteCluster.Region, "region", "", "region")
}
type getter func(o interface{}) interface{}
func (c *DeleteClusterCmd) Run() error {
if c.Region == "" {
var stateStore fi.StateStore
var err error
var cloud fi.Cloud
clusterName := ""
region := ""
if c.External {
region = c.Region
if region == "" {
return fmt.Errorf("--region is required")
}
clusterName := rootCommand.clusterName
if clusterName == "" {
return fmt.Errorf("--name is required")
return fmt.Errorf("--name is required (when --external)")
}
tags := map[string]string{"KubernetesCluster": clusterName}
cloud, err := awsup.NewAWSCloud(c.Region, tags)
cloud, err = awsup.NewAWSCloud(c.Region, tags)
if err != nil {
return fmt.Errorf("error initializing AWS client: %v", err)
}
} else {
stateStore, err = rootCommand.StateStore()
if err != nil {
return err
}
cluster, _, err := api.ReadConfig(stateStore)
if err != nil {
return err
}
if rootCommand.clusterName != cluster.Name {
return fmt.Errorf("sanity check failed: cluster name mismatch")
}
cloud, err = cloudup.BuildCloud(cluster)
if err != nil {
return err
}
}
d := &kutil.DeleteCluster{}
d.ClusterName = clusterName
d.Region = c.Region
d.Region = region
d.Cloud = cloud
resources, err := d.ListResources()
@ -71,9 +103,7 @@ func (c *DeleteClusterCmd) Run() error {
if len(resources) == 0 {
fmt.Printf("Nothing to delete\n")
return nil
}
} else {
columns := []string{"TYPE", "ID", "NAME"}
fields := []string{"Type", "ID", "Name"}
@ -134,5 +164,23 @@ func (c *DeleteClusterCmd) Run() error {
return fmt.Errorf("Must specify --yes to delete")
}
return d.DeleteResources(resources)
err := d.DeleteResources(resources)
if err != nil {
return err
}
}
if stateStore != nil {
if !c.Yes {
return fmt.Errorf("Must specify --yes to delete")
}
err := api.DeleteConfig(stateStore)
if err != nil {
return fmt.Errorf("error removing cluster from state store: %v", err)
}
}
fmt.Printf("\nCluster deleted\n")
return nil
}

View File

@ -96,20 +96,17 @@ func (c *DeleteCluster) ListResources() (map[string]*ResourceTracker, error) {
}
}
// TODO: Move to ListUntaggedInternetGateways?
{
// Gateways weren't tagged in kube-up
// If we are deleting the VPC, we should delete the attached gateway
// (no real reason not to; easy to recreate; no real state etc)
glog.V(2).Infof("Listing all Internet Gateways")
request := &ec2.DescribeInternetGatewaysInput{}
response, err := cloud.EC2.DescribeInternetGateways(request)
gateways, err := DescribeInternetGatewaysIgnoreTags(cloud)
if err != nil {
return nil, fmt.Errorf("error listing InternetGateways: %v", err)
return nil, err
}
for _, igw := range response.InternetGateways {
for _, igw := range gateways {
for _, attachment := range igw.Attachments {
vpcID := aws.StringValue(attachment.VpcId)
igwID := aws.StringValue(igw.InternetGatewayId)
@ -336,7 +333,8 @@ func ListInstances(cloud fi.Cloud, clusterName string) ([]*ResourceTracker, erro
continue
case "running":
// Fine
case "stopped":
// We need to delete
glog.V(4).Infof("instance %q has state=%q", id, stateName)
default:
@ -847,20 +845,14 @@ func DeleteInternetGateway(cloud fi.Cloud, r *ResourceTracker) error {
}
func ListInternetGateways(cloud fi.Cloud, clusterName string) ([]*ResourceTracker, error) {
c := cloud.(*awsup.AWSCloud)
glog.V(2).Infof("Listing EC2 InternetGateways")
request := &ec2.DescribeInternetGatewaysInput{
Filters: buildEC2Filters(cloud),
}
response, err := c.EC2.DescribeInternetGateways(request)
gateways, err := DescribeInternetGateways(cloud)
if err != nil {
return nil, fmt.Errorf("error listing InternetGateway: %v", err)
return nil, err
}
var trackers []*ResourceTracker
for _, o := range response.InternetGateways {
for _, o := range gateways {
tracker := &ResourceTracker{
Name: FindName(o.Tags),
ID: aws.StringValue(o.InternetGatewayId),
@ -882,6 +874,48 @@ func ListInternetGateways(cloud fi.Cloud, clusterName string) ([]*ResourceTracke
return trackers, nil
}
func DescribeInternetGateways(cloud fi.Cloud) ([]*ec2.InternetGateway, error) {
c := cloud.(*awsup.AWSCloud)
glog.V(2).Infof("Listing EC2 InternetGateways")
request := &ec2.DescribeInternetGatewaysInput{
Filters: buildEC2Filters(cloud),
}
response, err := c.EC2.DescribeInternetGateways(request)
if err != nil {
return nil, fmt.Errorf("error listing InternetGateway: %v", err)
}
var gateways []*ec2.InternetGateway
for _, o := range response.InternetGateways {
gateways = append(gateways, o)
}
return gateways, nil
}
// DescribeInternetGatewaysIgnoreTags returns all ec2.InternetGateways, ignoring tags
// (gateways were not always tagged in kube-up)
func DescribeInternetGatewaysIgnoreTags(cloud fi.Cloud) ([]*ec2.InternetGateway, error) {
c := cloud.(*awsup.AWSCloud)
glog.V(2).Infof("Listing all Internet Gateways")
request := &ec2.DescribeInternetGatewaysInput{}
response, err := c.EC2.DescribeInternetGateways(request)
if err != nil {
return nil, fmt.Errorf("error listing (all) InternetGateways: %v", err)
}
var gateways []*ec2.InternetGateway
for _, igw := range response.InternetGateways {
gateways = append(gateways, igw)
}
return gateways, nil
}
func DeleteVPC(cloud fi.Cloud, r *ResourceTracker) error {
c := cloud.(*awsup.AWSCloud)
@ -1082,15 +1116,49 @@ func DeleteELB(cloud fi.Cloud, r *ResourceTracker) error {
}
func ListELBs(cloud fi.Cloud, clusterName string) ([]*ResourceTracker, error) {
c := cloud.(*awsup.AWSCloud)
tags := c.Tags()
elbs, elbTags, err := DescribeELBs(cloud)
if err != nil {
return nil, err
}
var trackers []*ResourceTracker
for _, elb := range elbs {
id := aws.StringValue(elb.LoadBalancerName)
tracker := &ResourceTracker{
Name: FindELBName(elbTags[id]),
ID: id,
Type: "load-balancer",
deleter: DeleteELB,
}
var blocks []string
for _, sg := range elb.SecurityGroups {
blocks = append(blocks, "security-group:"+aws.StringValue(sg))
}
for _, s := range elb.Subnets {
blocks = append(blocks, "subnet:"+aws.StringValue(s))
}
blocks = append(blocks, "vpc:"+aws.StringValue(elb.VPCId))
tracker.blocks = blocks
trackers = append(trackers, tracker)
}
return trackers, nil
}
func DescribeELBs(cloud fi.Cloud) ([]*elb.LoadBalancerDescription, map[string][]*elb.Tag, error) {
c := cloud.(*awsup.AWSCloud)
tags := c.Tags()
glog.V(2).Infof("Listing all ELBs")
request := &elb.DescribeLoadBalancersInput{}
var elbs []*elb.LoadBalancerDescription
elbTags := make(map[string][]*elb.Tag)
var innerError error
err := c.ELB.DescribeLoadBalancersPages(request, func(p *elb.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancerDescriptions) == 0 {
@ -1120,37 +1188,21 @@ func ListELBs(cloud fi.Cloud, clusterName string) ([]*ResourceTracker, error) {
continue
}
tracker := &ResourceTracker{
Name: FindELBName(t.Tags),
ID: elbName,
Type: "load-balancer",
deleter: DeleteELB,
}
elbTags[elbName] = t.Tags
elb := nameToELB[elbName]
var blocks []string
for _, sg := range elb.SecurityGroups {
blocks = append(blocks, "security-group:"+aws.StringValue(sg))
}
for _, s := range elb.Subnets {
blocks = append(blocks, "subnet:"+aws.StringValue(s))
}
blocks = append(blocks, "vpc:"+aws.StringValue(elb.VPCId))
tracker.blocks = blocks
trackers = append(trackers, tracker)
elbs = append(elbs, elb)
}
return true
})
if err != nil {
return nil, fmt.Errorf("error describing LoadBalances: %v", err)
return nil, nil, fmt.Errorf("error describing LoadBalancers: %v", err)
}
if innerError != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
return nil, nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
}
return trackers, nil
return elbs, elbTags, nil
}
func DeleteElasticIP(cloud fi.Cloud, t *ResourceTracker) error {