Merge pull request #3719 from justinsb/tooldump_dump_instances

Automatic merge from submit-queue.

Refactor toolbox dump & dump structured instances
This commit is contained in:
Kubernetes Submit Queue 2017-10-29 10:25:43 -07:00 committed by GitHub
commit dd207dcd7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 368 additions and 277 deletions

View File

@ -76,7 +76,7 @@ go_library(
"//pkg/kubeconfig:go_default_library",
"//pkg/pretty:go_default_library",
"//pkg/resources:go_default_library",
"//pkg/resources/tracker:go_default_library",
"//pkg/resources/utils:go_default_library",
"//pkg/util/templater:go_default_library",
"//pkg/validation:go_default_library",
"//upup/pkg/fi:go_default_library",

View File

@ -26,7 +26,7 @@ import (
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/kubeconfig"
"k8s.io/kops/pkg/resources"
"k8s.io/kops/pkg/resources/tracker"
resourceutils "k8s.io/kops/pkg/resources/utils"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
@ -131,16 +131,12 @@ func RunDeleteCluster(f *util.Factory, out io.Writer, options *DeleteClusterOpti
}
}
d := &resources.ClusterResources{}
d.ClusterName = clusterName
d.Cloud = cloud
allResources, err := d.ListResources()
allResources, err := resourceutils.ListResources(cloud, clusterName, options.Region)
if err != nil {
return err
}
clusterResources := make(map[string]*tracker.Resource)
clusterResources := make(map[string]*resources.Resource)
for k, resource := range allResources {
if resource.Shared {
continue
@ -154,16 +150,16 @@ func RunDeleteCluster(f *util.Factory, out io.Writer, options *DeleteClusterOpti
wouldDeleteCloudResources = true
t := &tables.Table{}
t.AddColumn("TYPE", func(r *tracker.Resource) string {
t.AddColumn("TYPE", func(r *resources.Resource) string {
return r.Type
})
t.AddColumn("ID", func(r *tracker.Resource) string {
t.AddColumn("ID", func(r *resources.Resource) string {
return r.ID
})
t.AddColumn("NAME", func(r *tracker.Resource) string {
t.AddColumn("NAME", func(r *resources.Resource) string {
return r.Name
})
var l []*tracker.Resource
var l []*resources.Resource
for _, v := range clusterResources {
l = append(l, v)
}
@ -180,7 +176,7 @@ func RunDeleteCluster(f *util.Factory, out io.Writer, options *DeleteClusterOpti
fmt.Fprintf(out, "\n")
err = d.DeleteResources(clusterResources)
err = resources.DeleteResources(cloud, clusterResources)
if err != nil {
return err
}

View File

@ -21,11 +21,11 @@ import (
"fmt"
"io"
"github.com/golang/glog"
"github.com/spf13/cobra"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/resources"
resourceutils "k8s.io/kops/pkg/resources/utils"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
@ -107,38 +107,19 @@ func RunToolboxDump(f *util.Factory, out io.Writer, options *ToolboxDumpOptions)
return err
}
// Todo lets make this smart enough to detect the cloud and switch on the ClusterResources interface
d := &resources.ClusterResources{}
d.ClusterName = options.ClusterName
d.Cloud = cloud
resources, err := d.ListResources()
region := "" // Use default
resourceMap, err := resourceutils.ListResources(cloud, options.ClusterName, region)
if err != nil {
return err
}
dump, err := resources.BuildDump(resourceMap)
if err != nil {
return err
}
data := make(map[string]interface{})
dumpedResources := []interface{}{}
for k, r := range resources {
if r.Dumper == nil {
glog.V(8).Infof("skipping dump of %q (no Dumper)", k)
continue
}
o, err := r.Dumper(r)
if err != nil {
return fmt.Errorf("error dumping %q: %v", k, err)
}
if o != nil {
dumpedResources = append(dumpedResources, o)
}
}
data["resources"] = dumpedResources
switch options.Output {
case OutputYaml:
b, err := kops.ToRawYaml(data)
b, err := kops.ToRawYaml(dump)
if err != nil {
return fmt.Errorf("error marshaling yaml: %v", err)
}
@ -149,7 +130,7 @@ func RunToolboxDump(f *util.Factory, out io.Writer, options *ToolboxDumpOptions)
return nil
case OutputJSON:
b, err := json.MarshalIndent(data, "", " ")
b, err := json.MarshalIndent(dump, "", " ")
if err != nil {
return fmt.Errorf("error marshaling json: %v", err)
}

View File

@ -86,7 +86,7 @@ k8s.io/kops/pkg/pretty
k8s.io/kops/pkg/resources
k8s.io/kops/pkg/resources/digitalocean
k8s.io/kops/pkg/resources/digitalocean/dns
k8s.io/kops/pkg/resources/tracker
k8s.io/kops/pkg/resources/utils
k8s.io/kops/pkg/systemd
k8s.io/kops/pkg/templates
k8s.io/kops/pkg/testutils

View File

@ -5,16 +5,15 @@ go_library(
srcs = [
"aws.go",
"cluster_resources.go",
"do.go",
"dump.go",
"dumpmodel.go",
"gce.go",
"tracker.go",
"vsphere.go",
],
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/kops:go_default_library",
"//pkg/dns:go_default_library",
"//pkg/resources/digitalocean:go_default_library",
"//pkg/resources/tracker:go_default_library",
"//upup/pkg/fi:go_default_library",
"//upup/pkg/fi/cloudup/awsup:go_default_library",
"//upup/pkg/fi/cloudup/gce:go_default_library",
@ -45,7 +44,6 @@ go_test(
library = ":go_default_library",
deps = [
"//cloudmock/aws/mockec2:go_default_library",
"//pkg/resources/tracker:go_default_library",
"//upup/pkg/fi/cloudup/awsup:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/aws:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library",

View File

@ -32,7 +32,6 @@ import (
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kops/pkg/dns"
"k8s.io/kops/pkg/resources/tracker"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
)
@ -44,12 +43,10 @@ const (
TypeLoadBalancer = "load-balancer"
)
type listFn func(fi.Cloud, string) ([]*tracker.Resource, error)
type listFn func(fi.Cloud, string) ([]*Resource, error)
func (c *ClusterResources) listResourcesAWS() (map[string]*tracker.Resource, error) {
cloud := c.Cloud.(awsup.AWSCloud)
resources := make(map[string]*tracker.Resource)
func ListResourcesAWS(cloud awsup.AWSCloud, clusterName string) (map[string]*Resource, error) {
resources := make(map[string]*Resource)
// These are the functions that are used for looking up
// cluster resources by their tags.
@ -81,7 +78,7 @@ func (c *ClusterResources) listResourcesAWS() (map[string]*tracker.Resource, err
ListIAMRoles,
}
for _, fn := range listFunctions {
resourceTrackers, err := fn(cloud, c.ClusterName)
resourceTrackers, err := fn(cloud, clusterName)
if err != nil {
return nil, err
}
@ -109,7 +106,7 @@ func (c *ClusterResources) listResourcesAWS() (map[string]*tracker.Resource, err
}
vpc := resources["vpc:"+vpcID]
if vpc != nil && resources["internet-gateway:"+igwID] == nil {
resources["internet-gateway:"+igwID] = &tracker.Resource{
resources["internet-gateway:"+igwID] = &Resource{
Name: FindName(igw.Tags),
ID: igwID,
Type: "internet-gateway",
@ -141,13 +138,13 @@ func (c *ClusterResources) listResourcesAWS() (map[string]*tracker.Resource, err
}
}
if err := addUntaggedRouteTables(cloud, c.ClusterName, resources); err != nil {
if err := addUntaggedRouteTables(cloud, clusterName, resources); err != nil {
return nil, err
}
{
// We delete a NAT gateway if it is linked to our route table
routeTableIds := make(map[string]*tracker.Resource)
routeTableIds := make(map[string]*Resource)
for _, resource := range resources {
if resource.Type != ec2.ResourceTypeRouteTable {
continue
@ -185,7 +182,7 @@ func BuildEC2Filters(cloud fi.Cloud) []*ec2.Filter {
return filters
}
func addUntaggedRouteTables(cloud awsup.AWSCloud, clusterName string, resources map[string]*tracker.Resource) error {
func addUntaggedRouteTables(cloud awsup.AWSCloud, clusterName string, resources map[string]*Resource) error {
// We sometimes have trouble tagging the route table (eventual consistency, e.g. #597)
// If we are deleting the VPC, we should delete the route table
// (no real reason not to; easy to recreate; no real state etc)
@ -282,7 +279,7 @@ func matchesElbTags(tags map[string]string, actual []*elb.Tag) bool {
// Delete(cloud fi.Cloud) error
//}
func DeleteInstance(cloud fi.Cloud, t *tracker.Resource) error {
func DeleteInstance(cloud fi.Cloud, t *Resource) error {
c := cloud.(awsup.AWSCloud)
id := t.ID
@ -301,7 +298,7 @@ func DeleteInstance(cloud fi.Cloud, t *tracker.Resource) error {
return nil
}
func DeleteCloudFormationStack(cloud fi.Cloud, t *tracker.Resource) error {
func DeleteCloudFormationStack(cloud fi.Cloud, t *Resource) error {
c := cloud.(awsup.AWSCloud)
id := t.ID
@ -317,16 +314,17 @@ func DeleteCloudFormationStack(cloud fi.Cloud, t *tracker.Resource) error {
return nil
}
func DumpCloudFormationStack(r *tracker.Resource) (interface{}, error) {
func DumpCloudFormationStack(r *Resource, dump *Dump) error {
data := make(map[string]interface{})
data["id"] = r.ID
data["type"] = r.Type
data["raw"] = r.Obj
return data, nil
dump.Resources = append(dump.Resources, data)
return nil
}
func ListCloudFormationStacks(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
var resourceTrackers []*tracker.Resource
func ListCloudFormationStacks(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
var resourceTrackers []*Resource
request := &cloudformation.ListStacksInput{}
c := cloud.(awsup.AWSCloud)
response, err := c.CloudFormation().ListStacks(request)
@ -335,7 +333,7 @@ func ListCloudFormationStacks(cloud fi.Cloud, clusterName string) ([]*tracker.Re
}
for _, stack := range response.StackSummaries {
if *stack.StackName == clusterName {
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: *stack.StackName,
ID: *stack.StackId,
Type: "cloud-formation",
@ -350,7 +348,7 @@ func ListCloudFormationStacks(cloud fi.Cloud, clusterName string) ([]*tracker.Re
return resourceTrackers, nil
}
func ListInstances(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListInstances(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
c := cloud.(awsup.AWSCloud)
glog.V(2).Infof("Querying EC2 instances")
@ -358,7 +356,7 @@ func ListInstances(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, err
Filters: BuildEC2Filters(cloud),
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
err := c.EC2().DescribeInstancesPages(request, func(p *ec2.DescribeInstancesOutput, lastPage bool) bool {
for _, reservation := range p.Reservations {
@ -380,7 +378,7 @@ func ListInstances(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, err
}
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindName(instance.Tags),
ID: id,
Type: ec2.ResourceTypeInstance,
@ -419,15 +417,31 @@ func ListInstances(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, err
return resourceTrackers, nil
}
func DumpInstance(r *tracker.Resource) (interface{}, error) {
func DumpInstance(r *Resource, dump *Dump) error {
data := make(map[string]interface{})
data["id"] = r.ID
data["type"] = ec2.ResourceTypeInstance
data["raw"] = r.Obj
return data, nil
dump.Resources = append(dump.Resources, data)
ec2Instance := r.Obj.(*ec2.Instance)
i := &Instance{
Name: r.ID,
}
for _, networkInterface := range ec2Instance.NetworkInterfaces {
if networkInterface.Association != nil {
publicIP := aws.StringValue(networkInterface.Association.PublicIp)
if publicIP != "" {
i.PublicAddresses = append(i.PublicAddresses, publicIP)
}
}
}
dump.Instances = append(dump.Instances, i)
return nil
}
func DeleteSecurityGroup(cloud fi.Cloud, t *tracker.Resource) error {
func DeleteSecurityGroup(cloud fi.Cloud, t *Resource) error {
c := cloud.(awsup.AWSCloud)
id := t.ID
@ -482,24 +496,25 @@ func DeleteSecurityGroup(cloud fi.Cloud, t *tracker.Resource) error {
return nil
}
func DumpSecurityGroup(r *tracker.Resource) (interface{}, error) {
func DumpSecurityGroup(r *Resource, dump *Dump) error {
data := make(map[string]interface{})
data["id"] = r.ID
data["type"] = ec2.ResourceTypeSecurityGroup
data["raw"] = r.Obj
return data, nil
dump.Resources = append(dump.Resources, data)
return nil
}
func ListSecurityGroups(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListSecurityGroups(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
groups, err := DescribeSecurityGroups(cloud)
if err != nil {
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, sg := range groups {
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindName(sg.Tags),
ID: aws.StringValue(sg.GroupId),
Type: "security-group",
@ -534,7 +549,7 @@ func DescribeSecurityGroups(cloud fi.Cloud) ([]*ec2.SecurityGroup, error) {
return response.SecurityGroups, nil
}
func DeleteVolume(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteVolume(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -557,20 +572,20 @@ func DeleteVolume(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func ListVolumes(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListVolumes(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
c := cloud.(awsup.AWSCloud)
volumes, err := DescribeVolumes(cloud)
if err != nil {
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
elasticIPs := make(map[string]bool)
for _, volume := range volumes {
id := aws.StringValue(volume.VolumeId)
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindName(volume.Tags),
ID: id,
Type: "volume",
@ -612,7 +627,7 @@ func ListVolumes(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: ip,
ID: aws.StringValue(address.AllocationId),
Type: TypeElasticIp,
@ -650,7 +665,7 @@ func DescribeVolumes(cloud fi.Cloud) ([]*ec2.Volume, error) {
return volumes, nil
}
func DeleteKeypair(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteKeypair(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
name := r.Name
@ -666,7 +681,7 @@ func DeleteKeypair(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func ListKeypairs(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListKeypairs(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
if !strings.Contains(clusterName, ".") {
glog.Infof("cluster %q is legacy (kube-up) cluster; won't delete keypairs", clusterName)
return nil, nil
@ -686,14 +701,14 @@ func ListKeypairs(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, erro
return nil, fmt.Errorf("error listing KeyPairs: %v", err)
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, keypair := range response.KeyPairs {
name := aws.StringValue(keypair.KeyName)
if name != keypairName && !strings.HasPrefix(name, keypairName+"-") {
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: name,
ID: name,
Type: "keypair",
@ -719,7 +734,7 @@ func IsDependencyViolation(err error) bool {
}
}
func DeleteSubnet(cloud fi.Cloud, tracker *tracker.Resource) error {
func DeleteSubnet(cloud fi.Cloud, tracker *Resource) error {
c := cloud.(awsup.AWSCloud)
id := tracker.ID
@ -741,14 +756,14 @@ func DeleteSubnet(cloud fi.Cloud, tracker *tracker.Resource) error {
return nil
}
func ListSubnets(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListSubnets(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
c := cloud.(awsup.AWSCloud)
subnets, err := DescribeSubnets(cloud)
if err != nil {
return nil, fmt.Errorf("error listing subnets: %v", err)
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
elasticIPs := sets.NewString()
ownedElasticIPs := sets.NewString()
natGatewayIds := sets.NewString()
@ -757,7 +772,7 @@ func ListSubnets(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error
subnetID := aws.StringValue(subnet.SubnetId)
shared := HasSharedTag("subnet:"+subnetID, subnet.Tags, clusterName)
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindName(subnet.Tags),
ID: subnetID,
Type: "subnet",
@ -808,7 +823,7 @@ func ListSubnets(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: ip,
ID: aws.StringValue(address.AllocationId),
Type: TypeElasticIp,
@ -858,7 +873,7 @@ func ListSubnets(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: id,
ID: id,
Type: TypeNatGateway,
@ -895,7 +910,7 @@ func DescribeSubnets(cloud fi.Cloud) ([]*ec2.Subnet, error) {
return response.Subnets, nil
}
func DeleteRouteTable(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteRouteTable(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -949,13 +964,13 @@ func DescribeRouteTables(cloud fi.Cloud) ([]*ec2.RouteTable, error) {
return response.RouteTables, nil
}
func ListRouteTables(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListRouteTables(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
routeTables, err := DescribeRouteTables(cloud)
if err != nil {
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, rt := range routeTables {
resourceTracker := buildTrackerForRouteTable(rt)
@ -965,8 +980,8 @@ func ListRouteTables(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, e
return resourceTrackers, nil
}
func buildTrackerForRouteTable(rt *ec2.RouteTable) *tracker.Resource {
resourceTracker := &tracker.Resource{
func buildTrackerForRouteTable(rt *ec2.RouteTable) *Resource {
resourceTracker := &Resource{
Name: FindName(rt.Tags),
ID: aws.StringValue(rt.RouteTableId),
Type: ec2.ResourceTypeRouteTable,
@ -988,7 +1003,7 @@ func buildTrackerForRouteTable(rt *ec2.RouteTable) *tracker.Resource {
return resourceTracker
}
func DeleteDhcpOptions(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteDhcpOptions(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -1007,16 +1022,16 @@ func DeleteDhcpOptions(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func ListDhcpOptions(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListDhcpOptions(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
dhcpOptions, err := DescribeDhcpOptions(cloud)
if err != nil {
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, o := range dhcpOptions {
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindName(o.Tags),
ID: aws.StringValue(o.DhcpOptionsId),
Type: "dhcp-options",
@ -1048,7 +1063,7 @@ func DescribeDhcpOptions(cloud fi.Cloud) ([]*ec2.DhcpOptions, error) {
return response.DhcpOptions, nil
}
func DeleteInternetGateway(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteInternetGateway(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -1112,16 +1127,16 @@ func DeleteInternetGateway(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func ListInternetGateways(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListInternetGateways(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
gateways, err := DescribeInternetGateways(cloud)
if err != nil {
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, o := range gateways {
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindName(o.Tags),
ID: aws.StringValue(o.InternetGatewayId),
Type: "internet-gateway",
@ -1184,7 +1199,7 @@ func DescribeInternetGatewaysIgnoreTags(cloud fi.Cloud) ([]*ec2.InternetGateway,
return gateways, nil
}
func DeleteVPC(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteVPC(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -1203,12 +1218,13 @@ func DeleteVPC(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func DumpVPC(r *tracker.Resource) (interface{}, error) {
func DumpVPC(r *Resource, dump *Dump) error {
data := make(map[string]interface{})
data["id"] = r.ID
data["type"] = ec2.ResourceTypeVpc
data["raw"] = r.Obj
return data, nil
dump.Resources = append(dump.Resources, data)
return nil
}
func DescribeVPCs(cloud fi.Cloud) ([]*ec2.Vpc, error) {
@ -1226,17 +1242,17 @@ func DescribeVPCs(cloud fi.Cloud) ([]*ec2.Vpc, error) {
return response.Vpcs, nil
}
func ListVPCs(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListVPCs(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
vpcs, err := DescribeVPCs(cloud)
if err != nil {
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, v := range vpcs {
vpcID := aws.StringValue(v.VpcId)
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindName(v.Tags),
ID: vpcID,
Type: ec2.ResourceTypeVpc,
@ -1257,7 +1273,7 @@ func ListVPCs(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
return resourceTrackers, nil
}
func DeleteAutoScalingGroup(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteAutoScalingGroup(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -1277,7 +1293,7 @@ func DeleteAutoScalingGroup(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func ListAutoScalingGroups(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListAutoScalingGroups(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
c := cloud.(awsup.AWSCloud)
tags := c.Tags()
@ -1287,10 +1303,10 @@ func ListAutoScalingGroups(cloud fi.Cloud, clusterName string) ([]*tracker.Resou
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, asg := range asgs {
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindASGName(asg.Tags),
ID: aws.StringValue(asg.AutoScalingGroupName),
Type: "autoscaling-group",
@ -1315,12 +1331,12 @@ func ListAutoScalingGroups(cloud fi.Cloud, clusterName string) ([]*tracker.Resou
return resourceTrackers, nil
}
func FindAutoScalingLaunchConfigurations(cloud fi.Cloud, securityGroups sets.String) ([]*tracker.Resource, error) {
func FindAutoScalingLaunchConfigurations(cloud fi.Cloud, securityGroups sets.String) ([]*Resource, error) {
c := cloud.(awsup.AWSCloud)
glog.V(2).Infof("Finding all Autoscaling LaunchConfigurations by security group")
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
request := &autoscaling.DescribeLaunchConfigurationsInput{}
err := c.Autoscaling().DescribeLaunchConfigurationsPages(request, func(p *autoscaling.DescribeLaunchConfigurationsOutput, lastPage bool) bool {
@ -1336,7 +1352,7 @@ func FindAutoScalingLaunchConfigurations(cloud fi.Cloud, securityGroups sets.Str
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: aws.StringValue(t.LaunchConfigurationName),
ID: aws.StringValue(t.LaunchConfigurationName),
Type: TypeAutoscalingLaunchConfig,
@ -1359,7 +1375,7 @@ func FindAutoScalingLaunchConfigurations(cloud fi.Cloud, securityGroups sets.Str
return resourceTrackers, nil
}
func FindNatGateways(cloud fi.Cloud, routeTables map[string]*tracker.Resource) ([]*tracker.Resource, error) {
func FindNatGateways(cloud fi.Cloud, routeTables map[string]*Resource) ([]*Resource, error) {
if len(routeTables) == 0 {
return nil, nil
}
@ -1406,7 +1422,7 @@ func FindNatGateways(cloud fi.Cloud, routeTables map[string]*tracker.Resource) (
}
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
if len(natGatewayIds) != 0 {
request := &ec2.DescribeNatGatewaysInput{}
for natGatewayId := range natGatewayIds {
@ -1423,7 +1439,7 @@ func FindNatGateways(cloud fi.Cloud, routeTables map[string]*tracker.Resource) (
for _, t := range response.NatGateways {
natGatewayId := aws.StringValue(t.NatGatewayId)
ngwTracker := &tracker.Resource{
ngwTracker := &Resource{
Name: natGatewayId,
ID: natGatewayId,
Type: TypeNatGateway,
@ -1443,7 +1459,7 @@ func FindNatGateways(cloud fi.Cloud, routeTables map[string]*tracker.Resource) (
name = aws.StringValue(address.AllocationId)
}
eipTracker := &tracker.Resource{
eipTracker := &Resource{
Name: name,
ID: aws.StringValue(address.AllocationId),
Type: TypeElasticIp,
@ -1508,7 +1524,7 @@ func extractClusterName(userData string) string {
return clusterName
}
func DeleteAutoscalingLaunchConfiguration(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteAutoscalingLaunchConfiguration(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -1523,7 +1539,7 @@ func DeleteAutoscalingLaunchConfiguration(cloud fi.Cloud, r *tracker.Resource) e
return nil
}
func DeleteELB(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteELB(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
id := r.ID
@ -1542,24 +1558,25 @@ func DeleteELB(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func DumpELB(r *tracker.Resource) (interface{}, error) {
func DumpELB(r *Resource, dump *Dump) error {
data := make(map[string]interface{})
data["id"] = r.ID
data["type"] = TypeLoadBalancer
data["raw"] = r.Obj
return data, nil
dump.Resources = append(dump.Resources, data)
return nil
}
func ListELBs(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListELBs(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
elbs, elbTags, err := DescribeELBs(cloud)
if err != nil {
return nil, err
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, elb := range elbs {
id := aws.StringValue(elb.LoadBalancerName)
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: FindELBName(elbTags[id]),
ID: id,
Type: TypeLoadBalancer,
@ -1644,7 +1661,7 @@ func DescribeELBs(cloud fi.Cloud) ([]*elb.LoadBalancerDescription, map[string][]
return elbs, elbTags, nil
}
func DeleteElasticIP(cloud fi.Cloud, t *tracker.Resource) error {
func DeleteElasticIP(cloud fi.Cloud, t *Resource) error {
c := cloud.(awsup.AWSCloud)
id := t.ID
@ -1668,7 +1685,7 @@ func DeleteElasticIP(cloud fi.Cloud, t *tracker.Resource) error {
return nil
}
func DeleteNatGateway(cloud fi.Cloud, t *tracker.Resource) error {
func DeleteNatGateway(cloud fi.Cloud, t *Resource) error {
c := cloud.(awsup.AWSCloud)
id := t.ID
@ -1687,7 +1704,7 @@ func DeleteNatGateway(cloud fi.Cloud, t *tracker.Resource) error {
return nil
}
func deleteRoute53Records(cloud fi.Cloud, zone *route53.HostedZone, resourceTrackers []*tracker.Resource) error {
func deleteRoute53Records(cloud fi.Cloud, zone *route53.HostedZone, resourceTrackers []*Resource) error {
c := cloud.(awsup.AWSCloud)
var changes []*route53.Change
@ -1716,8 +1733,8 @@ func deleteRoute53Records(cloud fi.Cloud, zone *route53.HostedZone, resourceTrac
return nil
}
func ListRoute53Records(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
var resourceTrackers []*tracker.Resource
func ListRoute53Records(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
var resourceTrackers []*Resource
if dns.IsGossipHostname(clusterName) {
return resourceTrackers, nil
@ -1786,12 +1803,12 @@ func ListRoute53Records(cloud fi.Cloud, clusterName string) ([]*tracker.Resource
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: aws.StringValue(rrs.Name),
ID: hostedZoneID + "/" + aws.StringValue(rrs.Name),
Type: "route53-record",
GroupKey: hostedZoneID,
GroupDeleter: func(cloud fi.Cloud, resourceTrackers []*tracker.Resource) error {
GroupDeleter: func(cloud fi.Cloud, resourceTrackers []*Resource) error {
return deleteRoute53Records(cloud, zone, resourceTrackers)
},
Obj: rrs,
@ -1808,7 +1825,7 @@ func ListRoute53Records(cloud fi.Cloud, clusterName string) ([]*tracker.Resource
return resourceTrackers, nil
}
func DeleteIAMRole(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteIAMRole(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
roleName := r.Name
@ -1860,7 +1877,7 @@ func DeleteIAMRole(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func ListIAMRoles(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListIAMRoles(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
c := cloud.(awsup.AWSCloud)
remove := make(map[string]bool)
@ -1886,11 +1903,11 @@ func ListIAMRoles(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, erro
}
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, role := range roles {
name := aws.StringValue(role.RoleName)
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: name,
ID: name,
Type: "iam-role",
@ -1902,7 +1919,7 @@ func ListIAMRoles(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, erro
return resourceTrackers, nil
}
func DeleteIAMInstanceProfile(cloud fi.Cloud, r *tracker.Resource) error {
func DeleteIAMInstanceProfile(cloud fi.Cloud, r *Resource) error {
c := cloud.(awsup.AWSCloud)
profile := r.Obj.(*iam.InstanceProfile)
@ -1938,7 +1955,7 @@ func DeleteIAMInstanceProfile(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func ListIAMInstanceProfiles(cloud fi.Cloud, clusterName string) ([]*tracker.Resource, error) {
func ListIAMInstanceProfiles(cloud fi.Cloud, clusterName string) ([]*Resource, error) {
c := cloud.(awsup.AWSCloud)
remove := make(map[string]bool)
@ -1962,11 +1979,11 @@ func ListIAMInstanceProfiles(cloud fi.Cloud, clusterName string) ([]*tracker.Res
return nil, fmt.Errorf("error listing IAM instance profiles: %v", err)
}
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
for _, profile := range profiles {
name := aws.StringValue(profile.InstanceProfileName)
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: name,
ID: name,
Type: "iam-instance-profile",

View File

@ -24,13 +24,12 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"k8s.io/kops/cloudmock/aws/mockec2"
"k8s.io/kops/pkg/resources/tracker"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
)
func TestAddUntaggedRouteTables(t *testing.T) {
cloud := awsup.BuildMockAWSCloud("us-east-1", "abc")
resources := make(map[string]*tracker.Resource)
resources := make(map[string]*Resource)
clusterName := "me.example.com"
@ -72,7 +71,7 @@ func TestAddUntaggedRouteTables(t *testing.T) {
RouteTableId: aws.String("rt-5555"),
})
resources["vpc:vpc-1234"] = &tracker.Resource{}
resources["vpc:vpc-1234"] = &Resource{}
err := addUntaggedRouteTables(cloud, clusterName, resources)
if err != nil {

View File

@ -22,48 +22,13 @@ import (
"time"
"github.com/golang/glog"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/resources/tracker"
"k8s.io/kops/upup/pkg/fi"
)
var _ Resources = &ClusterResources{}
// Resources is a representation of a cluster with abilities to ListResources and DeleteResources
type Resources interface {
ListResources() (map[string]*tracker.Resource, error)
DeleteResources(resources map[string]*tracker.Resource) error
}
// ClusterResources is an implementation of Resources
// The algorithm is pretty simple: it discovers all the resources it can (primary using tags)
// There are a few tweaks to that approach, like choosing a default ordering, but it is not much smarter.
// Some dependencies are invisible (e.g. ELB dependencies).
type ClusterResources struct {
ClusterName string
Cloud fi.Cloud
Region string
}
func (c *ClusterResources) ListResources() (map[string]*tracker.Resource, error) {
switch c.Cloud.ProviderID() {
case kops.CloudProviderAWS:
return c.listResourcesAWS()
case kops.CloudProviderDO:
return c.listResourcesDO()
case kops.CloudProviderGCE:
return c.listResourcesGCE()
case kops.CloudProviderVSphere:
return c.listResourcesVSphere()
default:
return nil, fmt.Errorf("Delete on clusters on %q not (yet) supported", c.Cloud.ProviderID())
}
}
func (c *ClusterResources) DeleteResources(resources map[string]*tracker.Resource) error {
func DeleteResources(cloud fi.Cloud, resources map[string]*Resource) error {
depMap := make(map[string][]string)
done := make(map[string]*tracker.Resource)
done := make(map[string]*Resource)
var mutex sync.Mutex
@ -90,10 +55,10 @@ func (c *ClusterResources) DeleteResources(resources map[string]*tracker.Resourc
for {
// TODO: Some form of default ordering based on types?
failed := make(map[string]*tracker.Resource)
failed := make(map[string]*Resource)
for {
phase := make(map[string]*tracker.Resource)
phase := make(map[string]*Resource)
for k, r := range resources {
if _, d := done[k]; d {
@ -123,7 +88,7 @@ func (c *ClusterResources) DeleteResources(resources map[string]*tracker.Resourc
break
}
groups := make(map[string][]*tracker.Resource)
groups := make(map[string][]*Resource)
for k, t := range phase {
groupKey := t.GroupKey
if groupKey == "" {
@ -136,7 +101,7 @@ func (c *ClusterResources) DeleteResources(resources map[string]*tracker.Resourc
for _, trackers := range groups {
wg.Add(1)
go func(trackers []*tracker.Resource) {
go func(trackers []*Resource) {
mutex.Lock()
for _, t := range trackers {
k := t.Type + ":" + t.ID
@ -150,12 +115,12 @@ func (c *ClusterResources) DeleteResources(resources map[string]*tracker.Resourc
var err error
if trackers[0].GroupDeleter != nil {
err = trackers[0].GroupDeleter(c.Cloud, trackers)
err = trackers[0].GroupDeleter(cloud, trackers)
} else {
if len(trackers) != 1 {
glog.Fatalf("found group without groupKey")
}
err = trackers[0].Deleter(c.Cloud, trackers[0])
err = trackers[0].Deleter(cloud, trackers[0])
}
if err != nil {
mutex.Lock()

View File

@ -4,14 +4,15 @@ go_library(
name = "go_default_library",
srcs = [
"cloud.go",
"do.go",
"resources.go",
],
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/kops:go_default_library",
"//pkg/cloudinstances:go_default_library",
"//pkg/resources:go_default_library",
"//pkg/resources/digitalocean/dns:go_default_library",
"//pkg/resources/tracker:go_default_library",
"//upup/pkg/fi:go_default_library",
"//vendor/github.com/digitalocean/godo:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",

View File

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package resources
package digitalocean
import (
"k8s.io/kops/pkg/resources/digitalocean"
"k8s.io/kops/pkg/resources/tracker"
"k8s.io/kops/pkg/resources"
"k8s.io/kops/upup/pkg/fi"
)
func (c *ClusterResources) listResourcesDO() (map[string]*tracker.Resource, error) {
r := digitalocean.Resources{
Cloud: c.Cloud,
ClusterName: c.ClusterName,
func ListResources(cloud fi.Cloud, clusterName string) (map[string]*resources.Resource, error) {
r := Resources{
Cloud: cloud,
ClusterName: clusterName,
}
return r.ListResources()

View File

@ -17,7 +17,7 @@ limitations under the License.
package digitalocean
import (
"k8s.io/kops/pkg/resources/tracker"
"k8s.io/kops/pkg/resources"
"k8s.io/kops/upup/pkg/fi"
)
@ -27,11 +27,11 @@ type Resources struct {
}
// ListResources fetches all digitalocean resources into tracker.Resources
func (r *Resources) ListResources() (map[string]*tracker.Resource, error) {
func (r *Resources) ListResources() (map[string]*resources.Resource, error) {
return nil, nil
}
// DeleteResources deletes all resources passed in the form in tracker.Resources
func (r *Resources) DeleteResources(resources map[string]*tracker.Resource) error {
func (r *Resources) DeleteResources(resources map[string]*resources.Resource) error {
return nil
}

47
pkg/resources/dump.go Normal file
View File

@ -0,0 +1,47 @@
/*
Copyright 2017 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 resources
import (
"fmt"
"github.com/golang/glog"
)
// Dumpable is the interface that Resources that can report into the dump should implement
type Dumpable interface {
Dump(dump *Dump) error
}
// BuildDump gathers information about the cluster and returns an object for dumping
func BuildDump(resources map[string]*Resource) (*Dump, error) {
dump := &Dump{}
for k, r := range resources {
if r.Dumper == nil {
glog.V(8).Infof("skipping dump of %q (does not implement Dumpable)", k)
continue
}
err := r.Dumper(r, dump)
if err != nil {
return nil, fmt.Errorf("error dumping %q: %v", k, err)
}
}
return dump, nil
}

View File

@ -0,0 +1,29 @@
/*
Copyright 2017 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 resources
// Instance is the type for an instance in a dump
type Instance struct {
Name string `json:"name,omitempty"`
PublicAddresses []string `json:"publicAddresses,omitempty"`
}
// Dump is the type for a dump result
type Dump struct {
Resources []interface{} `json:"resources,omitempty"`
Instances []*Instance `json:"instances,omitempty"`
}

View File

@ -25,13 +25,12 @@ import (
compute "google.golang.org/api/compute/v0.beta"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kops/pkg/resources/tracker"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"k8s.io/kubernetes/federation/pkg/dnsprovider"
)
type gceListFn func() ([]*tracker.Resource, error)
type gceListFn func() ([]*Resource, error)
const (
typeInstance = "Instance"
@ -48,18 +47,17 @@ const (
// Maximum number of `-` separated tokens in a name
const maxPrefixTokens = 4
func (c *ClusterResources) listResourcesGCE() (map[string]*tracker.Resource, error) {
gceCloud := c.Cloud.(gce.GCECloud)
if c.Region == "" {
c.Region = gceCloud.Region()
func ListResourcesGCE(gceCloud gce.GCECloud, clusterName string, region string) (map[string]*Resource, error) {
if region == "" {
region = gceCloud.Region()
}
resources := make(map[string]*tracker.Resource)
resources := make(map[string]*Resource)
d := &clusterDiscoveryGCE{
cloud: c.Cloud,
cloud: gceCloud,
gceCloud: gceCloud,
clusterName: c.ClusterName,
clusterName: clusterName,
}
{
@ -73,13 +71,13 @@ func (c *ClusterResources) listResourcesGCE() (map[string]*tracker.Resource, err
if err != nil {
return nil, err
}
if u.Name != c.Region {
if u.Name != region {
continue
}
d.zones = append(d.zones, gceZone.Name)
}
if len(d.zones) == 0 {
return nil, fmt.Errorf("unable to determine zones in region %q", c.Region)
return nil, fmt.Errorf("unable to determine zones in region %q", region)
}
glog.Infof("Scanning zones: %v", d.zones)
}
@ -149,8 +147,8 @@ func (d *clusterDiscoveryGCE) findInstanceTemplates() ([]*compute.InstanceTempla
return d.instanceTemplates, nil
}
func (d *clusterDiscoveryGCE) listGCEInstanceTemplates() ([]*tracker.Resource, error) {
var resourceTrackers []*tracker.Resource
func (d *clusterDiscoveryGCE) listGCEInstanceTemplates() ([]*Resource, error) {
var resourceTrackers []*Resource
templates, err := d.findInstanceTemplates()
if err != nil {
@ -158,11 +156,11 @@ func (d *clusterDiscoveryGCE) listGCEInstanceTemplates() ([]*tracker.Resource, e
}
for _, t := range templates {
selfLink := t.SelfLink // avoid closure-in-loop go-tcha
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: t.Name,
ID: t.Name,
Type: typeInstanceTemplate,
Deleter: func(cloud fi.Cloud, r *tracker.Resource) error {
Deleter: func(cloud fi.Cloud, r *Resource) error {
return gce.DeleteInstanceTemplate(d.gceCloud, selfLink)
},
Obj: t,
@ -175,11 +173,11 @@ func (d *clusterDiscoveryGCE) listGCEInstanceTemplates() ([]*tracker.Resource, e
return resourceTrackers, nil
}
func (d *clusterDiscoveryGCE) listInstanceGroupManagersAndInstances() ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listInstanceGroupManagersAndInstances() ([]*Resource, error) {
c := d.gceCloud
project := c.Project()
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
instanceTemplates := make(map[string]*compute.InstanceTemplate)
{
@ -204,11 +202,11 @@ func (d *clusterDiscoveryGCE) listInstanceGroupManagersAndInstances() ([]*tracke
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: mig.Name,
ID: zoneName + "/" + mig.Name,
Type: typeInstanceGroupManager,
Deleter: func(cloud fi.Cloud, r *tracker.Resource) error { return gce.DeleteInstanceGroupManager(c, mig) },
Deleter: func(cloud fi.Cloud, r *Resource) error { return gce.DeleteInstanceGroupManager(c, mig) },
Obj: mig,
}
@ -234,10 +232,10 @@ func (d *clusterDiscoveryGCE) listInstanceGroupManagersAndInstances() ([]*tracke
return resourceTrackers, nil
}
func (d *clusterDiscoveryGCE) listManagedInstances(igm *compute.InstanceGroupManager) ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listManagedInstances(igm *compute.InstanceGroupManager) ([]*Resource, error) {
c := d.gceCloud
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
zoneName := gce.LastComponent(igm.Zone)
@ -250,13 +248,20 @@ func (d *clusterDiscoveryGCE) listManagedInstances(igm *compute.InstanceGroupMan
url := i.Instance // avoid closure-in-loop go-tcha
name := gce.LastComponent(url)
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: name,
ID: zoneName + "/" + name,
Type: typeInstance,
Deleter: func(cloud fi.Cloud, tracker *tracker.Resource) error {
Deleter: func(cloud fi.Cloud, tracker *Resource) error {
return gce.DeleteInstance(c, url)
},
Dumper: func(r *Resource, dump *Dump) error {
i := &Instance{
Name: name,
}
dump.Instances = append(dump.Instances, i)
return nil
},
Obj: i.Instance,
}
@ -313,15 +318,15 @@ func (d *clusterDiscoveryGCE) findGCEDisks() ([]*compute.Disk, error) {
return matches, nil
}
func (d *clusterDiscoveryGCE) listGCEDisks() ([]*tracker.Resource, error) {
var resourceTrackers []*tracker.Resource
func (d *clusterDiscoveryGCE) listGCEDisks() ([]*Resource, error) {
var resourceTrackers []*Resource
disks, err := d.findGCEDisks()
if err != nil {
return nil, err
}
for _, t := range disks {
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: t.Name,
ID: t.Name,
Type: typeDisk,
@ -340,7 +345,7 @@ func (d *clusterDiscoveryGCE) listGCEDisks() ([]*tracker.Resource, error) {
return resourceTrackers, nil
}
func deleteGCEDisk(cloud fi.Cloud, r *tracker.Resource) error {
func deleteGCEDisk(cloud fi.Cloud, r *Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.Disk)
@ -362,10 +367,10 @@ func deleteGCEDisk(cloud fi.Cloud, r *tracker.Resource) error {
return c.WaitForOp(op)
}
func (d *clusterDiscoveryGCE) listTargetPools() ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listTargetPools() ([]*Resource, error) {
c := d.gceCloud
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
ctx := context.Background()
@ -375,7 +380,7 @@ func (d *clusterDiscoveryGCE) listTargetPools() ([]*tracker.Resource, error) {
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: tp.Name,
ID: tp.Name,
Type: typeTargetPool,
@ -396,7 +401,7 @@ func (d *clusterDiscoveryGCE) listTargetPools() ([]*tracker.Resource, error) {
return resourceTrackers, nil
}
func deleteTargetPool(cloud fi.Cloud, r *tracker.Resource) error {
func deleteTargetPool(cloud fi.Cloud, r *Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.TargetPool)
@ -418,10 +423,10 @@ func deleteTargetPool(cloud fi.Cloud, r *tracker.Resource) error {
return c.WaitForOp(op)
}
func (d *clusterDiscoveryGCE) listForwardingRules() ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listForwardingRules() ([]*Resource, error) {
c := d.gceCloud
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
ctx := context.Background()
@ -431,7 +436,7 @@ func (d *clusterDiscoveryGCE) listForwardingRules() ([]*tracker.Resource, error)
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: fr.Name,
ID: fr.Name,
Type: typeForwardingRule,
@ -459,7 +464,7 @@ func (d *clusterDiscoveryGCE) listForwardingRules() ([]*tracker.Resource, error)
return resourceTrackers, nil
}
func deleteForwardingRule(cloud fi.Cloud, r *tracker.Resource) error {
func deleteForwardingRule(cloud fi.Cloud, r *Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.ForwardingRule)
@ -482,10 +487,10 @@ func deleteForwardingRule(cloud fi.Cloud, r *tracker.Resource) error {
}
// listFirewallRules discovers Firewall objects for the cluster
func (d *clusterDiscoveryGCE) listFirewallRules() ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listFirewallRules() ([]*Resource, error) {
c := d.gceCloud
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
ctx := context.Background()
@ -506,7 +511,7 @@ func (d *clusterDiscoveryGCE) listFirewallRules() ([]*tracker.Resource, error) {
break
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: fr.Name,
ID: fr.Name,
Type: typeFirewallRule,
@ -526,8 +531,8 @@ func (d *clusterDiscoveryGCE) listFirewallRules() ([]*tracker.Resource, error) {
return resourceTrackers, nil
}
// deleteFirewallRule is the helper function to delete a tracker.Resource for a Firewall object
func deleteFirewallRule(cloud fi.Cloud, r *tracker.Resource) error {
// deleteFirewallRule is the helper function to delete a Resource for a Firewall object
func deleteFirewallRule(cloud fi.Cloud, r *Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.Firewall)
@ -549,10 +554,10 @@ func deleteFirewallRule(cloud fi.Cloud, r *tracker.Resource) error {
return c.WaitForOp(op)
}
func (d *clusterDiscoveryGCE) listRoutes(resources map[string]*tracker.Resource) ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listRoutes(resources map[string]*Resource) ([]*Resource, error) {
c := d.gceCloud
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
instances := sets.NewString()
for _, resource := range resources {
@ -593,7 +598,7 @@ func (d *clusterDiscoveryGCE) listRoutes(resources map[string]*tracker.Resource)
}
if remove {
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: r.Name,
ID: r.Name,
Type: typeRoute,
@ -619,7 +624,7 @@ func (d *clusterDiscoveryGCE) listRoutes(resources map[string]*tracker.Resource)
return resourceTrackers, nil
}
func deleteRoute(cloud fi.Cloud, r *tracker.Resource) error {
func deleteRoute(cloud fi.Cloud, r *Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.Route)
@ -641,10 +646,10 @@ func deleteRoute(cloud fi.Cloud, r *tracker.Resource) error {
return c.WaitForOp(op)
}
func (d *clusterDiscoveryGCE) listAddresses() ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listAddresses() ([]*Resource, error) {
c := d.gceCloud
var resourceTrackers []*tracker.Resource
var resourceTrackers []*Resource
ctx := context.Background()
@ -655,7 +660,7 @@ func (d *clusterDiscoveryGCE) listAddresses() ([]*tracker.Resource, error) {
continue
}
resourceTracker := &tracker.Resource{
resourceTracker := &Resource{
Name: a.Name,
ID: a.Name,
Type: typeAddress,
@ -675,7 +680,7 @@ func (d *clusterDiscoveryGCE) listAddresses() ([]*tracker.Resource, error) {
return resourceTrackers, nil
}
func deleteAddress(cloud fi.Cloud, r *tracker.Resource) error {
func deleteAddress(cloud fi.Cloud, r *Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.Address)
@ -722,7 +727,7 @@ func (d *clusterDiscoveryGCE) matchesClusterNameMultipart(name string, maxParts
return false
}
func (d *clusterDiscoveryGCE) listGCEDNSZone() ([]*tracker.Resource, error) {
func (d *clusterDiscoveryGCE) listGCEDNSZone() ([]*Resource, error) {
// We never delete the hosted zone, because it is usually shared and we don't create it
return nil, nil
// TODO: When shared resource PR lands, reintroduce
@ -734,7 +739,7 @@ func (d *clusterDiscoveryGCE) listGCEDNSZone() ([]*tracker.Resource, error) {
// return nil, err
//}
//
//return []*tracker.Resource{
//return []*Resource{
// {
// Name: zone.Name(),
// ID: zone.Name(),
@ -770,7 +775,7 @@ func (d *clusterDiscoveryGCE) findDNSZone() (dnsprovider.Zone, error) {
return nil, fmt.Errorf("DNS Zone for cluster %s could not be found", d.clusterName)
}
func (d *clusterDiscoveryGCE) deleteDNSZone(cloud fi.Cloud, r *tracker.Resource) error {
func (d *clusterDiscoveryGCE) deleteDNSZone(cloud fi.Cloud, r *Resource) error {
clusterZone := r.Obj.(dnsprovider.Zone)
rrs, supported := clusterZone.ResourceRecordSets()

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package tracker
package resources
import (
"k8s.io/kops/upup/pkg/fi"
@ -36,7 +36,8 @@ type Resource struct {
GroupKey string
GroupDeleter func(cloud fi.Cloud, trackers []*Resource) error
Dumper func(r *Resource) (interface{}, error)
// Dumper populates the dump with any information from the resource
Dumper func(r *Resource, dump *Dump) error
Obj interface{}
}

View File

@ -1,8 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["tracker.go"],
visibility = ["//visibility:public"],
deps = ["//upup/pkg/fi:go_default_library"],
)

View File

@ -0,0 +1,16 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["collector.go"],
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/kops:go_default_library",
"//pkg/resources:go_default_library",
"//pkg/resources/digitalocean:go_default_library",
"//upup/pkg/fi:go_default_library",
"//upup/pkg/fi/cloudup/awsup:go_default_library",
"//upup/pkg/fi/cloudup/gce:go_default_library",
"//upup/pkg/fi/cloudup/vsphere:go_default_library",
],
)

View File

@ -0,0 +1,45 @@
/*
Copyright 2017 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 utils
import (
"fmt"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/resources"
"k8s.io/kops/pkg/resources/digitalocean"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"k8s.io/kops/upup/pkg/fi/cloudup/vsphere"
)
// ListResources collects the resources from the specified cloud
func ListResources(cloud fi.Cloud, clusterName string, region string) (map[string]*resources.Resource, error) {
switch cloud.ProviderID() {
case kops.CloudProviderAWS:
return resources.ListResourcesAWS(cloud.(awsup.AWSCloud), clusterName)
case kops.CloudProviderDO:
return digitalocean.ListResources(cloud, clusterName)
case kops.CloudProviderGCE:
return resources.ListResourcesGCE(cloud.(gce.GCECloud), clusterName, region)
case kops.CloudProviderVSphere:
return resources.ListResourcesVSphere(cloud.(*vsphere.VSphereCloud), clusterName)
default:
return nil, fmt.Errorf("delete on clusters on %q not (yet) supported", cloud.ProviderID())
}
}

View File

@ -18,10 +18,10 @@ package resources
import (
"context"
"github.com/golang/glog"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"k8s.io/kops/pkg/resources/tracker"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/vsphere"
)
@ -36,17 +36,15 @@ type clusterDiscoveryVSphere struct {
clusterName string
}
type vsphereListFn func() ([]*tracker.Resource, error)
type vsphereListFn func() ([]*Resource, error)
func (c *ClusterResources) listResourcesVSphere() (map[string]*tracker.Resource, error) {
vsphereCloud := c.Cloud.(*vsphere.VSphereCloud)
resources := make(map[string]*tracker.Resource)
func ListResourcesVSphere(cloud *vsphere.VSphereCloud, clusterName string) (map[string]*Resource, error) {
resources := make(map[string]*Resource)
d := &clusterDiscoveryVSphere{
cloud: c.Cloud,
vsphereCloud: vsphereCloud,
clusterName: c.ClusterName,
cloud: cloud,
vsphereCloud: cloud,
clusterName: clusterName,
}
listFunctions := []vsphereListFn{
@ -66,7 +64,7 @@ func (c *ClusterResources) listResourcesVSphere() (map[string]*tracker.Resource,
return resources, nil
}
func (d *clusterDiscoveryVSphere) listVMs() ([]*tracker.Resource, error) {
func (d *clusterDiscoveryVSphere) listVMs() ([]*Resource, error) {
c := d.vsphereCloud
regexForMasterVMs := "*" + "." + "masters" + "." + d.clusterName + "*"
@ -80,9 +78,9 @@ func (d *clusterDiscoveryVSphere) listVMs() ([]*tracker.Resource, error) {
glog.Warning(err)
}
var trackers []*tracker.Resource
var trackers []*Resource
for _, vm := range vms {
tracker := &tracker.Resource{
tracker := &Resource{
Name: vm.Name(),
ID: vm.Name(),
Type: typeVM,
@ -95,7 +93,7 @@ func (d *clusterDiscoveryVSphere) listVMs() ([]*tracker.Resource, error) {
return trackers, nil
}
func deleteVM(cloud fi.Cloud, r *tracker.Resource) error {
func deleteVM(cloud fi.Cloud, r *Resource) error {
vsphereCloud := cloud.(*vsphere.VSphereCloud)
vm := r.Obj.(*object.VirtualMachine)
@ -121,14 +119,15 @@ func deleteVM(cloud fi.Cloud, r *tracker.Resource) error {
return nil
}
func DumpVMInfo(r *tracker.Resource) (interface{}, error) {
func DumpVMInfo(r *Resource, dump *Dump) error {
data := make(map[string]interface{})
data["id"] = r.ID
data["type"] = r.Type
data["raw"] = r.Obj
return data, nil
dump.Resources = append(dump.Resources, data)
return nil
}
func GetResourceTrackerKey(t *tracker.Resource) string {
func GetResourceTrackerKey(t *Resource) string {
return t.Type + ":" + t.ID
}