Skip to content

Commit 5c7af87

Browse files
committed
Network tagging and cleanup are working
1 parent 244f5cf commit 5c7af87

12 files changed

+154
-31
lines changed

api/v1beta1/cloudstackcluster_webhook_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ var _ = Describe("CloudStackCluster webhooks", func() {
3131
clusterKind = "CloudStackCluster"
3232
clusterName = "test-cluster"
3333
clusterNamespace = "default"
34+
clusterId = "0"
3435
identitySecretName = "IdentitySecret"
3536
zone = "Zone"
3637
network = "Network"
@@ -47,6 +48,7 @@ var _ = Describe("CloudStackCluster webhooks", func() {
4748
ObjectMeta: metav1.ObjectMeta{
4849
Name: clusterName,
4950
Namespace: clusterNamespace,
51+
UID: clusterId,
5052
},
5153
Spec: CloudStackClusterSpec{
5254
IdentityRef: &CloudStackIdentityReference{
@@ -72,6 +74,7 @@ var _ = Describe("CloudStackCluster webhooks", func() {
7274
ObjectMeta: metav1.ObjectMeta{
7375
Name: clusterName,
7476
Namespace: clusterNamespace,
77+
UID: clusterId,
7578
},
7679
Spec: CloudStackClusterSpec{
7780
IdentityRef: &CloudStackIdentityReference{
@@ -96,6 +99,7 @@ var _ = Describe("CloudStackCluster webhooks", func() {
9699
ObjectMeta: metav1.ObjectMeta{
97100
Name: clusterName,
98101
Namespace: clusterNamespace,
102+
UID: clusterId,
99103
},
100104
Spec: CloudStackClusterSpec{
101105
IdentityRef: &CloudStackIdentityReference{
@@ -125,6 +129,7 @@ var _ = Describe("CloudStackCluster webhooks", func() {
125129
ObjectMeta: metav1.ObjectMeta{
126130
Name: clusterName,
127131
Namespace: clusterNamespace,
132+
UID: clusterId,
128133
},
129134
Spec: CloudStackClusterSpec{
130135
IdentityRef: &CloudStackIdentityReference{

controllers/cloudstackcluster_controller.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,9 @@ func (r *CloudStackClusterReconciler) reconcileDelete(
145145

146146
log.V(1).Info("reconcileDelete CloudStackCluster...")
147147

148-
// TODO Decide what resources to remove w/Cluster if any.
149-
// cloud.DestroyCluster(r.CS, csStackCluster)
148+
if err := r.CS.DisposeClusterResources(csCluster); err != nil {
149+
return ctrl.Result{}, err
150+
}
150151

151152
controllerutil.RemoveFinalizer(csCluster, infrav1.ClusterFinalizer)
152153
return ctrl.Result{}, nil

controllers/cloudstackcluster_controller_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func getCloudStackCluster() *infrav1.CloudStackCluster {
4040
ObjectMeta: metav1.ObjectMeta{
4141
GenerateName: "cs-cluster-test1-",
4242
Namespace: "default",
43+
UID: "0",
4344
},
4445
Spec: infrav1.CloudStackClusterSpec{
4546
Zone: "zone",

pkg/cloud/affinity_groups_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ package cloud_test
1818

1919
import (
2020
"errors"
21-
2221
"github.com/apache/cloudstack-go/v2/cloudstack"
2322
infrav1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
2423
"github.com/aws/cluster-api-provider-cloudstack/pkg/cloud"
2524
"github.com/golang/mock/gomock"
2625
. "github.com/onsi/ginkgo"
2726
. "github.com/onsi/gomega"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2828
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
2929
)
3030

@@ -49,8 +49,9 @@ var _ = Describe("AffinityGroup Unit Tests", func() {
4949
fakeAG = &cloud.AffinityGroup{
5050
Name: "FakeAffinityGroup",
5151
Type: cloud.AffinityGroupType}
52-
cluster = &infrav1.CloudStackCluster{Spec: infrav1.CloudStackClusterSpec{
53-
Zone: "Zone1", Network: "SharedGuestNet1"}}
52+
cluster = &infrav1.CloudStackCluster{
53+
Spec: infrav1.CloudStackClusterSpec{Zone: "Zone1", Network: "SharedGuestNet1"},
54+
ObjectMeta: metav1.ObjectMeta{UID: "0"}}
5455
machine = &infrav1.CloudStackMachine{Spec: infrav1.CloudStackMachineSpec{
5556
Offering: "Medium Instance", Template: "Ubuntu20"}}
5657
machine.ObjectMeta.SetName("rejoshed-affinity-group-test-vm")

pkg/cloud/cluster.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
type ClusterIface interface {
2626
GetOrCreateCluster(*infrav1.CloudStackCluster) error
27+
DisposeClusterResources(cluster *infrav1.CloudStackCluster) error
2728
}
2829

2930
func (c *client) resolveZone(csCluster *infrav1.CloudStackCluster) (retErr error) {
@@ -92,3 +93,7 @@ func (c *client) GetOrCreateCluster(csCluster *infrav1.CloudStackCluster) (retEr
9293
csCluster.Status.Ready = true
9394
return nil
9495
}
96+
97+
func (c *client) DisposeClusterResources(csCluster *infrav1.CloudStackCluster) (retError error) {
98+
return c.UntagAndDestroyNetwork(csCluster)
99+
}

pkg/cloud/cluster_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package cloud_test
1717

1818
import (
1919
"fmt"
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2021

2122
"github.com/apache/cloudstack-go/v2/cloudstack"
2223
infrav1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
@@ -58,7 +59,11 @@ var _ = Describe("Cluster", func() {
5859
cluster := &infrav1.CloudStackCluster{
5960
Spec: infrav1.CloudStackClusterSpec{
6061
Zone: zoneName,
61-
Network: netName}}
62+
Network: netName},
63+
ObjectMeta: metav1.ObjectMeta{
64+
UID: "0",
65+
},
66+
}
6267

6368
It("handles zone not found.", func() {
6469
expectedErr := fmt.Errorf("Not found")

pkg/cloud/instance_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package cloud_test
1818

1919
import (
2020
"fmt"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2122

2223
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
2324

@@ -64,8 +65,9 @@ var _ = Describe("Instance", func() {
6465
Template: "template-name"}}
6566
csMachine.Name = "instance-name"
6667
csCluster = &infrav1.CloudStackCluster{
67-
Spec: infrav1.CloudStackClusterSpec{},
68-
Status: infrav1.CloudStackClusterStatus{ZoneID: "zone-id"}}
68+
Spec: infrav1.CloudStackClusterSpec{},
69+
Status: infrav1.CloudStackClusterStatus{ZoneID: "zone-id"},
70+
ObjectMeta: metav1.ObjectMeta{UID: "0"}}
6971
machine = &capiv1.Machine{}
7072
})
7173

pkg/cloud/network.go

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,34 @@ func (c *client) ResolveNetwork(csCluster *infrav1.CloudStackCluster) (retErr er
5858
return nil
5959
}
6060

61+
func generateNetworkTagName(csCluster *infrav1.CloudStackCluster) string {
62+
return clusterTagNamePrefix + string(csCluster.UID)
63+
}
64+
6165
func (c *client) GetOrCreateNetwork(csCluster *infrav1.CloudStackCluster) (retErr error) {
6266
// Tag the network so we can clean it up later
63-
tagNetwork := func(csCluster *infrav1.CloudStackCluster, createdByCapc bool) error {
64-
clusterTag := "CAPC_cluster_" + string(csCluster.UID)
65-
tags := map[string]string{clusterTag: "1"}
66-
if createdByCapc {
67-
tags["created_by_CAPC"] = "1"
67+
tagNetwork := func(csCluster *infrav1.CloudStackCluster, addCreatedByTag bool) error {
68+
clusterTagName := generateNetworkTagName(csCluster)
69+
newTags := map[string]string{}
70+
71+
existingTags, err := c.GetNetworkTags(csCluster.Status.NetworkID)
72+
if err != nil {
73+
return err
74+
}
75+
76+
if existingTags[clusterTagName] == "" {
77+
newTags[clusterTagName] = "1"
78+
}
79+
80+
if addCreatedByTag {
81+
newTags[createdByCapcTagName] = "1"
82+
}
83+
84+
if len(newTags) > 0 {
85+
return c.AddNetworkTags(csCluster.Status.NetworkID, newTags)
6886
}
69-
return c.AddNetworkTags(csCluster.Status.NetworkID, tags)
87+
88+
return nil
7089
}
7190

7291
if retErr = c.ResolveNetwork(csCluster); retErr == nil { // Found network.
@@ -99,6 +118,32 @@ func (c *client) GetOrCreateNetwork(csCluster *infrav1.CloudStackCluster) (retEr
99118
return tagNetwork(csCluster, true)
100119
}
101120

121+
func (c *client) UntagAndDestroyNetwork(csCluster *infrav1.CloudStackCluster) (retError error) {
122+
tags, err := c.GetNetworkTags(csCluster.Status.NetworkID)
123+
if err != nil {
124+
return err
125+
}
126+
127+
var clusterTagCount int
128+
clusterTagName := generateNetworkTagName(csCluster)
129+
for tagName, tagValue := range tags {
130+
if strings.HasPrefix(tagName, clusterTagNamePrefix) {
131+
clusterTagCount++
132+
if tagName == clusterTagName {
133+
if err = c.DeleteNetworkTags(csCluster.Status.NetworkID, map[string]string{tagName: tagValue}); err != nil {
134+
return err
135+
}
136+
clusterTagCount--
137+
}
138+
}
139+
}
140+
141+
if clusterTagCount == 0 && tags[createdByCapcTagName] != "" {
142+
return c.DestroyNetwork(csCluster)
143+
}
144+
return nil
145+
}
146+
102147
func (c *client) ResolvePublicIPDetails(csCluster *infrav1.CloudStackCluster) (*cloudstack.PublicIpAddress, error) {
103148
ip := csCluster.Spec.ControlPlaneEndpoint.Host
104149

pkg/cloud/network_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
. "github.com/onsi/ginkgo"
2525
. "github.com/onsi/gomega"
2626
"github.com/pkg/errors"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2728
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
2829
)
2930

@@ -68,6 +69,9 @@ var _ = Describe("Network", func() {
6869
Network: fakeNetName,
6970
ControlPlaneEndpoint: clusterv1.APIEndpoint{Port: int32(6443)},
7071
},
72+
ObjectMeta: metav1.ObjectMeta{
73+
UID: "0",
74+
},
7175
}
7276
})
7377

pkg/cloud/tags.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ type TagIFace interface {
2222
DeleteNetworkTags(string, map[string]string) error
2323
}
2424

25-
const resourceTypeNetwork = "network"
25+
const (
26+
clusterTagNamePrefix = "CAPC_cluster_"
27+
createdByCapcTagName = "created_by_CAPC"
28+
resourceTypeNetwork = "network"
29+
)
2630

2731
// TagNetwork adds tags to a network by network id.
2832
func (c *client) AddNetworkTags(networkId string, tags map[string]string) error {

0 commit comments

Comments
 (0)