@@ -28,12 +28,16 @@ import (
28
28
compute "google.golang.org/api/compute/v1"
29
29
30
30
v1 "k8s.io/api/core/v1"
31
+ networkingv1beta1 "k8s.io/api/networking/v1beta1"
31
32
rbacv1 "k8s.io/api/rbac/v1"
32
33
apierrors "k8s.io/apimachinery/pkg/api/errors"
33
34
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34
35
"k8s.io/apimachinery/pkg/runtime/schema"
36
+ types "k8s.io/apimachinery/pkg/types"
37
+ "k8s.io/apimachinery/pkg/util/intstr"
35
38
"k8s.io/apimachinery/pkg/util/uuid"
36
39
"k8s.io/apimachinery/pkg/util/wait"
40
+ "k8s.io/apimachinery/pkg/watch"
37
41
"k8s.io/apiserver/pkg/authentication/serviceaccount"
38
42
"k8s.io/kubernetes/test/e2e/framework"
39
43
e2eauth "k8s.io/kubernetes/test/e2e/framework/auth"
@@ -935,3 +939,213 @@ func detectNegAnnotation(f *framework.Framework, jig *e2eingress.TestJig, gceCon
935
939
framework .ExpectNoError (err )
936
940
}
937
941
}
942
+
943
+ var _ = SIGDescribe ("Ingress API" , func () {
944
+ f := framework .NewDefaultFramework ("ingress" )
945
+ /*
946
+ Release: v1.19
947
+ Testname: Ingress API
948
+ Description:
949
+ The networking.k8s.io API group MUST exist in the /apis discovery document.
950
+ The networking.k8s.io/v1beta1 API group/version MUST exist in the /apis/networking.k8s.io discovery document.
951
+ The ingresses resources MUST exist in the /apis/networking.k8s.io/v1beta1 discovery document.
952
+ The ingresses resource must support create, get, list, watch, update, patch, delete, and deletecollection.
953
+ The ingresses/status resource must support update and patch
954
+
955
+ */
956
+
957
+ ginkgo .It ("should support creating Ingress API operations" , func () {
958
+ // Setup
959
+ ns := f .Namespace .Name
960
+ ingVersion := "v1beta1"
961
+ ingClient := f .ClientSet .NetworkingV1beta1 ().Ingresses (ns )
962
+
963
+ prefixPathType := networkingv1beta1 .PathTypePrefix
964
+
965
+ ingTemplate := & networkingv1beta1.Ingress {
966
+ ObjectMeta : metav1.ObjectMeta {GenerateName : "e2e-example-ing" ,
967
+ Labels : map [string ]string {
968
+ "special-label" : f .UniqueName ,
969
+ }},
970
+ Spec : networkingv1beta1.IngressSpec {
971
+ Backend : & networkingv1beta1.IngressBackend {
972
+ ServiceName : "default-backend" ,
973
+ ServicePort : intstr .FromInt (8080 ),
974
+ },
975
+ Rules : []networkingv1beta1.IngressRule {
976
+ {
977
+ Host : "foo.bar.com" ,
978
+ IngressRuleValue : networkingv1beta1.IngressRuleValue {
979
+ HTTP : & networkingv1beta1.HTTPIngressRuleValue {
980
+ Paths : []networkingv1beta1.HTTPIngressPath {{
981
+ Path : "/" ,
982
+ PathType : & prefixPathType ,
983
+ Backend : networkingv1beta1.IngressBackend {
984
+ ServiceName : "test-backend" ,
985
+ ServicePort : intstr .FromInt (8080 ),
986
+ },
987
+ }},
988
+ },
989
+ },
990
+ },
991
+ },
992
+ },
993
+ Status : networkingv1beta1.IngressStatus {LoadBalancer : v1.LoadBalancerStatus {}},
994
+ }
995
+ // Discovery
996
+ ginkgo .By ("getting /apis" )
997
+ {
998
+ discoveryGroups , err := f .ClientSet .Discovery ().ServerGroups ()
999
+ framework .ExpectNoError (err )
1000
+ found := false
1001
+ for _ , group := range discoveryGroups .Groups {
1002
+ if group .Name == networkingv1beta1 .GroupName {
1003
+ for _ , version := range group .Versions {
1004
+ if version .Version == ingVersion {
1005
+ found = true
1006
+ break
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+ framework .ExpectEqual (found , true , fmt .Sprintf ("expected networking API group/version, got %#v" , discoveryGroups .Groups ))
1012
+ }
1013
+
1014
+ ginkgo .By ("getting /apis/networking.k8s.io" )
1015
+ {
1016
+ group := & metav1.APIGroup {}
1017
+ err := f .ClientSet .Discovery ().RESTClient ().Get ().AbsPath ("/apis/networking.k8s.io" ).Do (context .TODO ()).Into (group )
1018
+ framework .ExpectNoError (err )
1019
+ found := false
1020
+ for _ , version := range group .Versions {
1021
+ if version .Version == ingVersion {
1022
+ found = true
1023
+ break
1024
+ }
1025
+ }
1026
+ framework .ExpectEqual (found , true , fmt .Sprintf ("expected networking API version, got %#v" , group .Versions ))
1027
+ }
1028
+
1029
+ ginkgo .By ("getting /apis/networking.k8s.io" + ingVersion )
1030
+ {
1031
+ resources , err := f .ClientSet .Discovery ().ServerResourcesForGroupVersion (networkingv1beta1 .SchemeGroupVersion .String ())
1032
+ framework .ExpectNoError (err )
1033
+ foundIngress := false
1034
+ for _ , resource := range resources .APIResources {
1035
+ switch resource .Name {
1036
+ case "ingresses" :
1037
+ foundIngress = true
1038
+ }
1039
+ }
1040
+ framework .ExpectEqual (foundIngress , true , fmt .Sprintf ("expected ingresses, got %#v" , resources .APIResources ))
1041
+ }
1042
+
1043
+ // Ingress resource create/read/update/watch verbs
1044
+ ginkgo .By ("creating" )
1045
+ _ , err := ingClient .Create (context .TODO (), ingTemplate , metav1.CreateOptions {})
1046
+ framework .ExpectNoError (err )
1047
+ _ , err = ingClient .Create (context .TODO (), ingTemplate , metav1.CreateOptions {})
1048
+ framework .ExpectNoError (err )
1049
+ createdIngress , err := ingClient .Create (context .TODO (), ingTemplate , metav1.CreateOptions {})
1050
+ framework .ExpectNoError (err )
1051
+
1052
+ ginkgo .By ("getting" )
1053
+ gottenIngress , err := ingClient .Get (context .TODO (), createdIngress .Name , metav1.GetOptions {})
1054
+ framework .ExpectNoError (err )
1055
+ framework .ExpectEqual (gottenIngress .UID , createdIngress .UID )
1056
+
1057
+ ginkgo .By ("listing" )
1058
+ ings , err := ingClient .List (context .TODO (), metav1.ListOptions {LabelSelector : "special-label=" + f .UniqueName })
1059
+ framework .ExpectNoError (err )
1060
+ framework .ExpectEqual (len (ings .Items ), 3 , "filtered list should have 3 items" )
1061
+
1062
+ ginkgo .By ("watching" )
1063
+ framework .Logf ("starting watch" )
1064
+ ingWatch , err := ingClient .Watch (context .TODO (), metav1.ListOptions {ResourceVersion : ings .ResourceVersion , LabelSelector : "special-label=" + f .UniqueName })
1065
+ framework .ExpectNoError (err )
1066
+
1067
+ // Test cluster-wide list and watch
1068
+ clusterIngClient := f .ClientSet .NetworkingV1beta1 ().Ingresses ("" )
1069
+ ginkgo .By ("cluster-wide listing" )
1070
+ clusterIngs , err := clusterIngClient .List (context .TODO (), metav1.ListOptions {LabelSelector : "special-label=" + f .UniqueName })
1071
+ framework .ExpectNoError (err )
1072
+ framework .ExpectEqual (len (clusterIngs .Items ), 3 , "filtered list should have 3 items" )
1073
+
1074
+ ginkgo .By ("cluster-wide watching" )
1075
+ framework .Logf ("starting watch" )
1076
+ _ , err = clusterIngClient .Watch (context .TODO (), metav1.ListOptions {ResourceVersion : ings .ResourceVersion , LabelSelector : "special-label=" + f .UniqueName })
1077
+ framework .ExpectNoError (err )
1078
+
1079
+ ginkgo .By ("patching" )
1080
+ patchedIngress , err := ingClient .Patch (context .TODO (), createdIngress .Name , types .MergePatchType , []byte (`{"metadata":{"annotations":{"patched":"true"}}}` ), metav1.PatchOptions {})
1081
+ framework .ExpectNoError (err )
1082
+ framework .ExpectEqual (patchedIngress .Annotations ["patched" ], "true" , "patched object should have the applied annotation" )
1083
+
1084
+ ginkgo .By ("updating" )
1085
+ ingToUpdate := patchedIngress .DeepCopy ()
1086
+ ingToUpdate .Annotations ["updated" ] = "true"
1087
+ updatedIngress , err := ingClient .Update (context .TODO (), ingToUpdate , metav1.UpdateOptions {})
1088
+ framework .ExpectNoError (err )
1089
+ framework .ExpectEqual (updatedIngress .Annotations ["updated" ], "true" , "updated object should have the applied annotation" )
1090
+
1091
+ framework .Logf ("waiting for watch events with expected annotations" )
1092
+ for sawAnnotations := false ; ! sawAnnotations ; {
1093
+ select {
1094
+ case evt , ok := <- ingWatch .ResultChan ():
1095
+ framework .ExpectEqual (ok , true , "watch channel should not close" )
1096
+ framework .ExpectEqual (evt .Type , watch .Modified )
1097
+ watchedIngress , isIngress := evt .Object .(* networkingv1beta1.Ingress )
1098
+ framework .ExpectEqual (isIngress , true , fmt .Sprintf ("expected Ingress, got %T" , evt .Object ))
1099
+ if watchedIngress .Annotations ["patched" ] == "true" {
1100
+ framework .Logf ("saw patched and updated annotations" )
1101
+ sawAnnotations = true
1102
+ ingWatch .Stop ()
1103
+ } else {
1104
+ framework .Logf ("missing expected annotations, waiting: %#v" , watchedIngress .Annotations )
1105
+ }
1106
+ case <- time .After (wait .ForeverTestTimeout ):
1107
+ framework .Fail ("timed out waiting for watch event" )
1108
+ }
1109
+ }
1110
+
1111
+ // /status subresource operations
1112
+ ginkgo .By ("patching /status" )
1113
+ lbStatus := v1.LoadBalancerStatus {
1114
+ Ingress : []v1.LoadBalancerIngress {{IP : "169.1.1.1" }},
1115
+ }
1116
+ lbStatusJSON , err := json .Marshal (lbStatus )
1117
+ framework .ExpectNoError (err )
1118
+ patchedStatus , err := ingClient .Patch (context .TODO (), createdIngress .Name , types .MergePatchType ,
1119
+ []byte (`{"metadata":{"annotations":{"patchedstatus":"true"}},"status":{"loadBalancer":` + string (lbStatusJSON )+ `}}` ),
1120
+ metav1.PatchOptions {}, "status" )
1121
+ framework .ExpectNoError (err )
1122
+ framework .ExpectEqual (patchedStatus .Status .LoadBalancer , lbStatus , "patched object should have the applied loadBalancer status" )
1123
+ framework .ExpectEqual (patchedStatus .Annotations ["patchedstatus" ], "true" , "patched object should have the applied annotation" )
1124
+
1125
+ ginkgo .By ("updating /status" )
1126
+ statusToUpdate := patchedStatus .DeepCopy ()
1127
+ statusToUpdate .Status .LoadBalancer = v1.LoadBalancerStatus {
1128
+ Ingress : []v1.LoadBalancerIngress {{IP : "169.1.1.2" }},
1129
+ }
1130
+ updatedStatus , err := ingClient .UpdateStatus (context .TODO (), statusToUpdate , metav1.UpdateOptions {})
1131
+ framework .ExpectNoError (err )
1132
+ framework .ExpectEqual (updatedStatus .Status .LoadBalancer , statusToUpdate .Status .LoadBalancer , fmt .Sprintf ("updated object expected to have updated loadbalancer status %#v, got %#v" , statusToUpdate .Status .LoadBalancer , updatedStatus .Status .LoadBalancer ))
1133
+
1134
+ // Ingress resource delete operations
1135
+ ginkgo .By ("deleting" )
1136
+ err = ingClient .Delete (context .TODO (), createdIngress .Name , metav1.DeleteOptions {})
1137
+ framework .ExpectNoError (err )
1138
+ _ , err = ingClient .Get (context .TODO (), createdIngress .Name , metav1.GetOptions {})
1139
+ framework .ExpectEqual (apierrors .IsNotFound (err ), true , fmt .Sprintf ("expected 404, got %#v" , err ))
1140
+ ings , err = ingClient .List (context .TODO (), metav1.ListOptions {LabelSelector : "special-label=" + f .UniqueName })
1141
+ framework .ExpectNoError (err )
1142
+ framework .ExpectEqual (len (ings .Items ), 2 , "filtered list should have 2 items" )
1143
+
1144
+ ginkgo .By ("deleting a collection" )
1145
+ err = ingClient .DeleteCollection (context .TODO (), metav1.DeleteOptions {}, metav1.ListOptions {LabelSelector : "special-label=" + f .UniqueName })
1146
+ framework .ExpectNoError (err )
1147
+ ings , err = ingClient .List (context .TODO (), metav1.ListOptions {LabelSelector : "special-label=" + f .UniqueName })
1148
+ framework .ExpectNoError (err )
1149
+ framework .ExpectEqual (len (ings .Items ), 0 , "filtered list should have 0 items" )
1150
+ })
1151
+ })
0 commit comments