@@ -25,6 +25,7 @@ import (
25
25
. "github.com/onsi/ginkgo/v2"
26
26
. "github.com/onsi/gomega"
27
27
corev1 "k8s.io/api/core/v1"
28
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
28
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
30
"k8s.io/klog/v2"
30
31
"k8s.io/utils/ptr"
@@ -879,6 +880,274 @@ var _ = Describe("Hetzner ClusterReconciler", func() {
879
880
}, timeout ).Should (BeTrue ())
880
881
},
881
882
)
883
+
884
+ Describe ("For an existing Network" , func () {
885
+ It ("should attach the existing unlabeled Network by ID and not create a new one" , func () {
886
+ networkName := utils .GenerateName (nil , "network1-" )
887
+ network , err := hcloudClient .CreateNetwork (context .Background (), hcloud.NetworkCreateOpts {Name : networkName })
888
+ Expect (err ).To (Succeed ())
889
+ defer func () {
890
+ err := hcloudClient .DeleteNetwork (context .Background (), network )
891
+ Expect (err ).To (Succeed ())
892
+ }()
893
+ networksBeforeClusterCreate , err := hcloudClient .ListNetworks (context .Background (), hcloud.NetworkListOpts {})
894
+ Expect (err ).To (Succeed ())
895
+
896
+ hetznerClusterName := utils .GenerateName (nil , "test1-" )
897
+
898
+ capiCluster := & clusterv1.Cluster {
899
+ ObjectMeta : metav1.ObjectMeta {
900
+ GenerateName : "capi-test1-" ,
901
+ Namespace : namespace ,
902
+ Finalizers : []string {clusterv1 .ClusterFinalizer },
903
+ },
904
+ Spec : clusterv1.ClusterSpec {
905
+ InfrastructureRef : & corev1.ObjectReference {
906
+ APIVersion : infrav1 .GroupVersion .String (),
907
+ Kind : "HetznerCluster" ,
908
+ Name : hetznerClusterName ,
909
+ Namespace : namespace ,
910
+ },
911
+ },
912
+ }
913
+ Expect (testEnv .Create (ctx , capiCluster )).To (Succeed ())
914
+ defer func () {
915
+ Expect (testEnv .Cleanup (ctx , capiCluster )).To (Succeed ())
916
+ }()
917
+
918
+ instance := & infrav1.HetznerCluster {
919
+ ObjectMeta : metav1.ObjectMeta {
920
+ Name : hetznerClusterName ,
921
+ Namespace : namespace ,
922
+ OwnerReferences : []metav1.OwnerReference {
923
+ {
924
+ APIVersion : "cluster.x-k8s.io/v1beta1" ,
925
+ Kind : "Cluster" ,
926
+ Name : capiCluster .Name ,
927
+ UID : capiCluster .UID ,
928
+ },
929
+ },
930
+ },
931
+ Spec : getDefaultHetznerClusterSpec (),
932
+ }
933
+ // the creation of a HetznerCluster should not lead to the creation of a network when the ID of an
934
+ // existing network was given.
935
+ instance .Spec .HCloudNetwork .ID = ptr .To (network .ID )
936
+ Expect (testEnv .Create (ctx , instance )).To (Succeed ())
937
+ defer func () {
938
+ Expect (testEnv .Cleanup (ctx , instance )).To (Succeed ())
939
+ }()
940
+
941
+ key := client.ObjectKey {Namespace : instance .Namespace , Name : instance .Name }
942
+
943
+ Eventually (func () bool {
944
+ if err := testEnv .Get (ctx , key , instance ); err != nil {
945
+ return false
946
+ }
947
+ if isPresentAndTrue (key , instance , infrav1 .NetworkReadyCondition ) && instance .Status .Network != nil {
948
+ return true
949
+ }
950
+ return false
951
+ }, timeout ).Should (BeTrue ())
952
+
953
+ networksAfterClusterCreate , err := hcloudClient .ListNetworks (ctx , hcloud.NetworkListOpts {})
954
+ Expect (err ).To (Succeed ())
955
+
956
+ Expect (len (networksAfterClusterCreate )).To (Equal (len (networksBeforeClusterCreate )))
957
+
958
+ var found bool
959
+ for _ , n := range networksAfterClusterCreate {
960
+ if n .ID == instance .Status .Network .ID {
961
+ found = true
962
+ break
963
+ }
964
+ }
965
+ Expect (found ).To (Equal (true ))
966
+ })
967
+ It ("should not delete the existing unlabeled Network when deleting the Cluster" , func () {
968
+ networkName := utils .GenerateName (nil , "network2-" )
969
+ network , err := hcloudClient .CreateNetwork (context .Background (), hcloud.NetworkCreateOpts {Name : networkName })
970
+ Expect (err ).To (Succeed ())
971
+ defer func () {
972
+ err := hcloudClient .DeleteNetwork (context .Background (), network )
973
+ Expect (err ).To (Succeed ())
974
+ }()
975
+ networksBeforeClusterDelete , err := hcloudClient .ListNetworks (context .Background (), hcloud.NetworkListOpts {})
976
+ Expect (err ).To (Succeed ())
977
+
978
+ hetznerClusterName := utils .GenerateName (nil , "test1-" )
979
+
980
+ capiCluster := & clusterv1.Cluster {
981
+ ObjectMeta : metav1.ObjectMeta {
982
+ GenerateName : "capi-test1-" ,
983
+ Namespace : namespace ,
984
+ Finalizers : []string {clusterv1 .ClusterFinalizer },
985
+ },
986
+ Spec : clusterv1.ClusterSpec {
987
+ InfrastructureRef : & corev1.ObjectReference {
988
+ APIVersion : infrav1 .GroupVersion .String (),
989
+ Kind : "HetznerCluster" ,
990
+ Name : hetznerClusterName ,
991
+ Namespace : namespace ,
992
+ },
993
+ },
994
+ }
995
+ Expect (testEnv .Create (ctx , capiCluster )).To (Succeed ())
996
+
997
+ instance := & infrav1.HetznerCluster {
998
+ ObjectMeta : metav1.ObjectMeta {
999
+ Name : hetznerClusterName ,
1000
+ Namespace : namespace ,
1001
+ OwnerReferences : []metav1.OwnerReference {
1002
+ {
1003
+ APIVersion : "cluster.x-k8s.io/v1beta1" ,
1004
+ Kind : "Cluster" ,
1005
+ Name : capiCluster .Name ,
1006
+ UID : capiCluster .UID ,
1007
+ },
1008
+ },
1009
+ },
1010
+ Spec : getDefaultHetznerClusterSpec (),
1011
+ }
1012
+ instance .Spec .HCloudNetwork .ID = ptr .To (network .ID )
1013
+ Expect (testEnv .Create (ctx , instance )).To (Succeed ())
1014
+
1015
+ key := client.ObjectKey {Namespace : instance .Namespace , Name : instance .Name }
1016
+
1017
+ var networkID * int64
1018
+ Eventually (func () bool {
1019
+ if err := testEnv .Get (ctx , key , instance ); err != nil {
1020
+ return false
1021
+ }
1022
+ if isPresentAndTrue (key , instance , infrav1 .NetworkReadyCondition ) && instance .Status .Network != nil {
1023
+ networkID = & instance .Status .Network .ID
1024
+ return true
1025
+ }
1026
+ return false
1027
+ }, timeout ).Should (BeTrue ())
1028
+
1029
+ Expect (networkID ).ToNot (BeNil ())
1030
+
1031
+ // the deletion of a HetznerCluster should not lead to the deletion of an existing network
1032
+ // when the network misses the `owned` label.
1033
+ Expect (testEnv .Cleanup (ctx , instance , capiCluster )).To (Succeed ())
1034
+
1035
+ Eventually (func () bool {
1036
+ if err := testEnv .Get (ctx , client.ObjectKey {Namespace : instance .Namespace , Name : instance .Name }, instance ); err != nil && apierrors .IsNotFound (err ) {
1037
+ return true
1038
+ } else if err != nil {
1039
+ return false
1040
+ }
1041
+ return false
1042
+ }, timeout ).Should (BeTrue ())
1043
+
1044
+ networksAfterClusterDelete , err := hcloudClient .ListNetworks (ctx , hcloud.NetworkListOpts {})
1045
+ Expect (err ).To (Succeed ())
1046
+
1047
+ Expect (len (networksAfterClusterDelete )).To (Equal (len (networksBeforeClusterDelete )))
1048
+
1049
+ var found bool
1050
+ for _ , n := range networksAfterClusterDelete {
1051
+ if n .ID == * networkID {
1052
+ found = true
1053
+ break
1054
+ }
1055
+ }
1056
+ Expect (found ).To (Equal (true ))
1057
+ })
1058
+ It (`should delete the existing "owned" labeled Network when deleting the Cluster` , func () {
1059
+ hetznerClusterName := utils .GenerateName (nil , "test1-" )
1060
+
1061
+ capiCluster := & clusterv1.Cluster {
1062
+ ObjectMeta : metav1.ObjectMeta {
1063
+ GenerateName : "capi-test1-" ,
1064
+ Namespace : namespace ,
1065
+ Finalizers : []string {clusterv1 .ClusterFinalizer },
1066
+ },
1067
+ Spec : clusterv1.ClusterSpec {
1068
+ InfrastructureRef : & corev1.ObjectReference {
1069
+ APIVersion : infrav1 .GroupVersion .String (),
1070
+ Kind : "HetznerCluster" ,
1071
+ Name : hetznerClusterName ,
1072
+ Namespace : namespace ,
1073
+ },
1074
+ },
1075
+ }
1076
+ Expect (testEnv .Create (ctx , capiCluster )).To (Succeed ())
1077
+
1078
+ instance := & infrav1.HetznerCluster {
1079
+ ObjectMeta : metav1.ObjectMeta {
1080
+ Name : hetznerClusterName ,
1081
+ Namespace : namespace ,
1082
+ OwnerReferences : []metav1.OwnerReference {
1083
+ {
1084
+ APIVersion : "cluster.x-k8s.io/v1beta1" ,
1085
+ Kind : "Cluster" ,
1086
+ Name : capiCluster .Name ,
1087
+ UID : capiCluster .UID ,
1088
+ },
1089
+ },
1090
+ },
1091
+ Spec : getDefaultHetznerClusterSpec (),
1092
+ }
1093
+
1094
+ networkName := utils .GenerateName (nil , "network3-" )
1095
+ network , err := hcloudClient .CreateNetwork (context .Background (), hcloud.NetworkCreateOpts {
1096
+ Name : networkName ,
1097
+ Labels : map [string ]string {instance .ClusterTagKey (): "owned" },
1098
+ })
1099
+ Expect (err ).To (Succeed ())
1100
+
1101
+ networksBeforeClusterDelete , err := hcloudClient .ListNetworks (context .Background (), hcloud.NetworkListOpts {})
1102
+ Expect (err ).To (Succeed ())
1103
+
1104
+ instance .Spec .HCloudNetwork .ID = ptr .To (network .ID )
1105
+ Expect (testEnv .Create (ctx , instance )).To (Succeed ())
1106
+
1107
+ key := client.ObjectKey {Namespace : instance .Namespace , Name : instance .Name }
1108
+
1109
+ var networkID * int64
1110
+ Eventually (func () bool {
1111
+ if err := testEnv .Get (ctx , key , instance ); err != nil {
1112
+ return false
1113
+ }
1114
+ if isPresentAndTrue (key , instance , infrav1 .NetworkReadyCondition ) && instance .Status .Network != nil {
1115
+ networkID = & instance .Status .Network .ID
1116
+ return true
1117
+ }
1118
+ return false
1119
+ }, timeout ).Should (BeTrue ())
1120
+
1121
+ Expect (networkID ).ToNot (BeNil ())
1122
+
1123
+ // As the network has the `owned` label, the deletion of a HetznerCluster will also lead to the
1124
+ // deletion of the network.
1125
+ Expect (testEnv .Cleanup (ctx , instance , capiCluster )).To (Succeed ())
1126
+
1127
+ Eventually (func () bool {
1128
+ if err := testEnv .Get (ctx , client.ObjectKey {Namespace : instance .Namespace , Name : instance .Name }, instance ); err != nil && apierrors .IsNotFound (err ) {
1129
+ return true
1130
+ } else if err != nil {
1131
+ return false
1132
+ }
1133
+ return false
1134
+ }, timeout ).Should (BeTrue ())
1135
+
1136
+ networksAfterClusterDelete , err := hcloudClient .ListNetworks (ctx , hcloud.NetworkListOpts {})
1137
+ Expect (err ).To (Succeed ())
1138
+
1139
+ Expect (len (networksAfterClusterDelete )).To (Equal (len (networksBeforeClusterDelete ) - 1 ))
1140
+
1141
+ var found bool
1142
+ for _ , n := range networksAfterClusterDelete {
1143
+ if n .ID == * networkID {
1144
+ found = true
1145
+ break
1146
+ }
1147
+ }
1148
+ Expect (found ).To (Not (Equal (true )))
1149
+ })
1150
+ })
882
1151
})
883
1152
})
884
1153
})
0 commit comments