9
9
"os/exec"
10
10
"path"
11
11
"strings"
12
+ "sync"
12
13
"time"
13
14
14
15
aadpodid "github.com/Azure/aad-pod-identity/pkg/apis/aadpodidentity/v1"
@@ -873,8 +874,107 @@ var _ = Describe("Kubernetes cluster using aad-pod-identity", func() {
873
874
Expect (err ).NotTo (HaveOccurred ())
874
875
Expect (ok ).To (Equal (true ))
875
876
})
877
+
878
+ It ("should pass multiple identity validating test even when MIC is failing over" , func () {
879
+ // Two go routines - one which keeps assigning identities by means of identity validator assignment.
880
+ iterations := 2
881
+ var wg sync.WaitGroup
882
+ wg .Add (2 )
883
+
884
+ go func (iterations int ) {
885
+ defer wg .Done ()
886
+ runMICDisrupt (iterations )
887
+ fmt .Printf ("Disrupting MIC completed %d iterations\n " , iterations )
888
+ }(iterations )
889
+
890
+ go func (iterations int ) {
891
+ defer wg .Done ()
892
+ runValidatorTest (iterations )
893
+ fmt .Printf ("Validator tests completed %d iterations\n " , iterations )
894
+ }(iterations )
895
+
896
+ wg .Wait ()
897
+ fmt .Printf ("Done with running validator test and disrupting MIC" )
898
+ })
876
899
})
877
900
901
+ func runValidatorTest (iterations int ) {
902
+ defer GinkgoRecover ()
903
+ replicas := "1"
904
+ data := infra.IdentityValidatorTemplateData {
905
+ Name : identityValidator ,
906
+ IdentityBinding : keyvaultIdentity ,
907
+ Registry : cfg .Registry ,
908
+ IdentityValidatorVersion : cfg .IdentityValidatorVersion ,
909
+ Replicas : replicas ,
910
+ }
911
+ var err error
912
+
913
+ for i := 0 ; i < iterations ; i ++ {
914
+ fmt .Printf ("Starting identity validator. Iteration: %d\n " , i )
915
+
916
+ if i == 0 {
917
+ // Initial creation of identity, binding and identityvalidator pod.
918
+ setUpIdentityAndDeployment (keyvaultIdentity , "" , "1" )
919
+ } else { // After the initial one only create and delete the identity validator.
920
+ err = infra .CreateIdentityValidator (cfg .SubscriptionID , cfg .ResourceGroup , templateOutputPath , data )
921
+ Expect (err ).NotTo (HaveOccurred ())
922
+ }
923
+
924
+ ok , err := deploy .WaitOnReady (identityValidator )
925
+ Expect (err ).NotTo (HaveOccurred ())
926
+ Expect (ok ).To (Equal (true ))
927
+
928
+ ok , err = azureassignedidentity .WaitOnLengthMatched (1 )
929
+ Expect (err ).NotTo (HaveOccurred ())
930
+ Expect (ok ).To (Equal (true ))
931
+
932
+ azureAssignedIdentity , err := azureassignedidentity .GetByPrefix (identityValidator )
933
+ Expect (err ).NotTo (HaveOccurred ())
934
+ validateAzureAssignedIdentity (azureAssignedIdentity , keyvaultIdentity )
935
+
936
+ deleteAllIdentityValidator ()
937
+
938
+ ok , err = azureassignedidentity .WaitOnLengthMatched (0 )
939
+ Expect (err ).NotTo (HaveOccurred ())
940
+ Expect (ok ).To (Equal (true ))
941
+ }
942
+ fmt .Printf ("Completing %d validation checks\n " , iterations )
943
+ }
944
+
945
+ func runMICDisrupt (iterations int ) {
946
+ defer GinkgoRecover ()
947
+ delay := time .Second * 60
948
+ for i := 0 ; i < iterations ; i ++ {
949
+ fmt .Printf ("Starting MIC disruptor. Iteration: %d\n " , i )
950
+ leader , err := getMICLeader ()
951
+ Expect (err ).NotTo (HaveOccurred ())
952
+ fmt .Printf ("MIC leader: %s\n " , leader )
953
+ Expect (pod .DeletePod (leader )).NotTo (HaveOccurred ())
954
+ waitForLeaderChange (leader )
955
+ // Wait for some time for MIC to go through some iterations.
956
+ time .Sleep (delay )
957
+ }
958
+ fmt .Printf ("Completing disrupting MIC %d times.\n " , iterations )
959
+ }
960
+
961
+ func waitForLeaderChange (checkLeader string ) {
962
+ // Total 60 seconds for leader change.
963
+ retries := 12
964
+ sleepTime := time .Second * 5
965
+
966
+ for i := 0 ; i < retries ; i ++ {
967
+ currentLeader , err := getMICLeader ()
968
+ Expect (err ).NotTo (HaveOccurred ())
969
+ if ! strings .EqualFold (currentLeader , checkLeader ) {
970
+ fmt .Printf ("Leader changed from %s to %s\n " , checkLeader , currentLeader )
971
+ return
972
+ }
973
+ time .Sleep (sleepTime )
974
+ }
975
+ Expect (false ).Should (Equal (true ), "Leader change did not happen in 60 seconds" )
976
+ }
977
+
878
978
func collectLogs (podName , dir string ) {
879
979
pods , err := pod .GetAllNameByPrefix (podName )
880
980
Expect (err ).NotTo (HaveOccurred ())
@@ -948,20 +1048,21 @@ func collectDebuggingInfo() {
948
1048
collectLogs ("nmi" , logDirName )
949
1049
collectLogs ("identityvalidator" , logDirName )
950
1050
collectLogs ("busybox" , logDirName )
951
-
952
1051
}
953
1052
954
1053
func getMICLeader () (string , error ) {
955
1054
cmd := exec .Command ("kubectl" , "get" , "endpoints" , "aad-pod-identity-mic" , "-o" , "json" )
956
1055
output , err := cmd .CombinedOutput ()
957
1056
Expect (err ).NotTo (HaveOccurred ())
958
1057
1058
+ const leAnnotation = "control-plane.alpha.kubernetes.io/leader"
1059
+
959
1060
ep := & corev1.Endpoints {}
960
1061
if err := json .Unmarshal (output , & ep ); err != nil {
961
1062
return "" , errors .Wrap (err , "Failed to unmarshall json" )
962
1063
}
963
1064
964
- leRecordStr := ep .Annotations ["control-plane.alpha.kubernetes.io/leader" ]
1065
+ leRecordStr := ep .Annotations [leAnnotation ]
965
1066
if leRecordStr == "" {
966
1067
return "" , fmt .Errorf ("Leader election record empty " )
967
1068
}
@@ -1142,6 +1243,7 @@ func validateUserAssignedIdentityOnPod(podName, identityClientID string) ([]byte
1142
1243
"--keyvault-name" , cfg .KeyvaultName ,
1143
1244
"--keyvault-secret-name" , cfg .KeyvaultSecretName ,
1144
1245
"--keyvault-secret-version" , cfg .KeyvaultSecretVersion )
1246
+ util .PrintCommand (cmd )
1145
1247
return cmd .CombinedOutput ()
1146
1248
}
1147
1249
@@ -1153,6 +1255,7 @@ func validateClusterWideUserAssignedIdentity(podName, identityClientID string) (
1153
1255
"--subscription-id" , cfg .SubscriptionID ,
1154
1256
"--resource-group" , cfg .ResourceGroup ,
1155
1257
"--identity-client-id" , identityClientID )
1258
+ util .PrintCommand (cmd )
1156
1259
return cmd .CombinedOutput ()
1157
1260
}
1158
1261
0 commit comments