diff --git a/test/extended/apiserver/api_requests.go b/test/extended/apiserver/api_requests.go index bd4b25f15e60..eb5e5aecea8a 100644 --- a/test/extended/apiserver/api_requests.go +++ b/test/extended/apiserver/api_requests.go @@ -11,7 +11,6 @@ import ( apiserverv1 "github.com/openshift/api/apiserver/v1" configv1 "github.com/openshift/api/config/v1" apiserverclientv1 "github.com/openshift/client-go/apiserver/clientset/versioned/typed/apiserver/v1" - configclient "github.com/openshift/client-go/config/clientset/versioned" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/test/e2e/framework" e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" @@ -96,13 +95,7 @@ var _ = g.Describe("[sig-arch][Late]", func() { apirequestCountClient, err := apiserverclientv1.NewForConfig(oc.AdminConfig()) o.Expect(err).NotTo(o.HaveOccurred()) - clientConfig, err := framework.LoadConfig(true) - o.Expect(err).NotTo(o.HaveOccurred()) - - configClient, err := configclient.NewForConfig(clientConfig) - o.Expect(err).NotTo(o.HaveOccurred()) - - infra, err := configClient.ConfigV1().Infrastructures().Get(context.Background(), "cluster", metav1.GetOptions{}) + infra, err := oc.AdminConfigClient().ConfigV1().Infrastructures().Get(context.Background(), "cluster", metav1.GetOptions{}) o.Expect(err).NotTo(o.HaveOccurred()) type platformUpperBound map[string]int64 diff --git a/test/extended/cli/admin.go b/test/extended/cli/admin.go index 7a635c56413f..6c92c3f9df2a 100644 --- a/test/extended/cli/admin.go +++ b/test/extended/cli/admin.go @@ -363,7 +363,7 @@ var _ = g.Describe("[sig-cli] oc adm", func() { oc.Run("delete").Args("-f", "-").InputString(policyClusterRoles).Execute() }) - g.It("role-selectors", func() { + g.It("role-selectors [apigroup:template.openshift.io]", func() { clusterRole := gen.GenerateName("basic-user2-") clusterBinding := gen.GenerateName("basic-users2-") // template processing requires a namespaced client diff --git a/test/extended/cli/apiresources.go b/test/extended/cli/apiresources.go index be1def8c8957..4fedc70a5ef6 100644 --- a/test/extended/cli/apiresources.go +++ b/test/extended/cli/apiresources.go @@ -16,19 +16,12 @@ var _ = g.Describe("[sig-cli] oc api-resources", func() { out, err := oc.Run("api-resources").Output() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("configmaps")) - o.Expect(out).To(o.ContainSubstring("images")) - o.Expect(out).To(o.ContainSubstring("imagestreamtags")) o.Expect(out).To(o.ContainSubstring("jobs")) o.Expect(out).To(o.ContainSubstring("nodes")) o.Expect(out).To(o.ContainSubstring("pods")) o.Expect(out).To(o.ContainSubstring("secrets")) o.Expect(out).To(o.ContainSubstring("services")) - out, err = oc.Run("api-resources").Args("--api-group=build.openshift.io").Output() - o.Expect(err).NotTo(o.HaveOccurred()) - o.Expect(out).To(o.ContainSubstring("builds")) - o.Expect(out).To(o.ContainSubstring("buildconfigs")) - out, err = oc.Run("api-resources").Args("--namespaced=false").Output() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("clusterroles")) @@ -41,19 +34,53 @@ var _ = g.Describe("[sig-cli] oc api-resources", func() { o.Expect(out).To(o.ContainSubstring("serviceaccounts")) o.Expect(out).To(o.ContainSubstring("deployments")) - out, err = oc.Run("api-resources").Args("--verbs=get").Output() - o.Expect(err).NotTo(o.HaveOccurred()) - o.Expect(out).To(o.ContainSubstring("configs")) - o.Expect(out).To(o.ContainSubstring("routes")) - o.Expect(out).To(o.ContainSubstring("volumesnapshots")) - out, err = oc.Run("api-versions").Output() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("apps/v1")) o.Expect(out).To(o.ContainSubstring("networking.k8s.io/v1")) o.Expect(out).To(o.ContainSubstring("node.k8s.io/v1")) + o.Expect(out).To(o.ContainSubstring("storage.k8s.io/v1")) + }) + + g.It("can output expected information about build.openshift.io api-resources [apigroup:build.openshift.io]", func() { + out, err := oc.Run("api-resources").Args("--api-group=build.openshift.io").Output() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(out).To(o.ContainSubstring("builds")) + o.Expect(out).To(o.ContainSubstring("buildconfigs")) + }) + + g.It("can output expected information about image.openshift.io api-resources [apigroup:image.openshift.io]", func() { + out, err := oc.Run("api-resources").Output() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(out).To(o.ContainSubstring("images")) + o.Expect(out).To(o.ContainSubstring("imagestreamtags")) + }) + + g.It("can output expected information about operator.openshift.io api-resources [apigroup:operator.openshift.io]", func() { + out, err := oc.Run("api-resources").Args("--verbs=get").Output() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(out).To(o.ContainSubstring("configs")) + }) + + g.It("can output expected information about project.openshift.io api-resources [apigroup:project.openshift.io]", func() { + out, err := oc.Run("api-versions").Output() + o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("project.openshift.io/v1")) + }) + + g.It("can output expected information about route.openshift.io api-resources and api-version [apigroup:route.openshift.io]", func() { + out, err := oc.Run("api-resources").Args("--verbs=get").Output() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(out).To(o.ContainSubstring("routes")) + + out, err = oc.Run("api-versions").Output() + o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("route.openshift.io/v1")) - o.Expect(out).To(o.ContainSubstring("storage.k8s.io/v1")) + }) + + g.It("can output expected information about snapshot.storage.k8s.io api-resources [apigroup:snapshot.storage.k8s.io]", func() { + out, err := oc.Run("api-resources").Args("--verbs=get").Output() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(out).To(o.ContainSubstring("volumesnapshots")) }) }) diff --git a/test/extended/cli/basics.go b/test/extended/cli/basics.go index 2796df1634ee..64d7f1529f1c 100644 --- a/test/extended/cli/basics.go +++ b/test/extended/cli/basics.go @@ -65,7 +65,7 @@ var _ = g.Describe("[sig-cli] oc basics", func() { o.Expect(err).NotTo(o.HaveOccurred()) }) - g.It("can create deploymentconfig and clusterquota", func() { + g.It("can create deploymentconfig and clusterquota [apigroup:apps.openshift.io]", func() { nginx := k8simage.GetE2EImage(k8simage.Nginx) tools := "image-registry.openshift-image-registry.svc:5000/openshift/tools:latest" @@ -101,7 +101,7 @@ var _ = g.Describe("[sig-cli] oc basics", func() { o.Expect(err).NotTo(o.HaveOccurred()) }) - g.It("can patch resources", func() { + g.It("can patch resources [apigroup:user.openshift.io]", func() { // need admin here ocAdmin := oc.AsAdmin() @@ -136,7 +136,7 @@ var _ = g.Describe("[sig-cli] oc basics", func() { o.Expect(err).NotTo(o.HaveOccurred()) }) - g.It("can describe an OAuth access token", func() { + g.It("can describe an OAuth access token [apigroup:oauth.openshift.io]", func() { // need admin here ocAdmin := oc.AsAdmin() @@ -165,7 +165,7 @@ var _ = g.Describe("[sig-cli] oc basics", func() { o.Expect(out).To(o.ContainSubstring("job.batch/foo")) }) - g.It("can process templates", func() { + g.It("can process templates [apigroup:template.openshift.io]", func() { name := filepath.Join(os.TempDir(), "template.json") out, err := oc.Run("process").Args("-f", templateFile, "-l", "name=mytemplate").Output() diff --git a/test/extended/cli/compat.go b/test/extended/cli/compat.go index 956cfb8c6ca0..bd2661317308 100644 --- a/test/extended/cli/compat.go +++ b/test/extended/cli/compat.go @@ -29,8 +29,8 @@ var _ = g.Describe("[sig-cli] oc", func() { oc = exutil.NewCLIWithPodSecurityLevel("cli", admissionapi.LevelBaseline) - g.It("can run inside of a busybox container", func() { - ns = oc.Namespace() + g.It("can run inside of a busybox container [apigroup:image.openshift.io]", func() { + ns := oc.Namespace() cli := oc.KubeFramework().PodClient() _, err := oc.KubeClient().RbacV1().RoleBindings(ns).Create(context.Background(), &rbacv1.RoleBinding{ diff --git a/test/extended/cli/explain.go b/test/extended/cli/explain.go index 361799dd6528..b3fce32afabb 100644 --- a/test/extended/cli/explain.go +++ b/test/extended/cli/explain.go @@ -21,7 +21,6 @@ import ( e2e "k8s.io/kubernetes/test/e2e/framework" configv1 "github.com/openshift/api/config/v1" - configclient "github.com/openshift/client-go/config/clientset/versioned" "github.com/openshift/origin/test/extended/networking" exutil "github.com/openshift/origin/test/extended/util" ) @@ -33,25 +32,33 @@ type explainExceptions struct { } var ( - builtinTypes = []schema.GroupVersionResource{ - {Group: "apps.openshift.io", Version: "v1", Resource: "deploymentconfigs"}, - - {Group: "build.openshift.io", Version: "v1", Resource: "buildconfigs"}, - {Group: "build.openshift.io", Version: "v1", Resource: "builds"}, - - {Group: "image.openshift.io", Version: "v1", Resource: "imagestreamimports"}, - {Group: "image.openshift.io", Version: "v1", Resource: "imagestreams"}, - {Group: "image.openshift.io", Version: "v1", Resource: "imagetags"}, - - {Group: "project.openshift.io", Version: "v1", Resource: "projects"}, - - {Group: "route.openshift.io", Version: "v1", Resource: "routes"}, - - {Group: "security.openshift.io", Version: "v1", Resource: "podsecuritypolicyreviews"}, - {Group: "security.openshift.io", Version: "v1", Resource: "podsecuritypolicyselfsubjectreviews"}, - {Group: "security.openshift.io", Version: "v1", Resource: "podsecuritypolicysubjectreviews"}, - - {Group: "template.openshift.io", Version: "v1", Resource: "templateinstances"}, + builtinTypes = map[string][]schema.GroupVersionResource{ + "apps.openshift.io": { + {Group: "apps.openshift.io", Version: "v1", Resource: "deploymentconfigs"}, + }, + "build.openshift.io": { + {Group: "build.openshift.io", Version: "v1", Resource: "buildconfigs"}, + {Group: "build.openshift.io", Version: "v1", Resource: "builds"}, + }, + "image.openshift.io": { + {Group: "image.openshift.io", Version: "v1", Resource: "imagestreamimports"}, + {Group: "image.openshift.io", Version: "v1", Resource: "imagestreams"}, + {Group: "image.openshift.io", Version: "v1", Resource: "imagetags"}, + }, + "project.openshift.io": { + {Group: "project.openshift.io", Version: "v1", Resource: "projects"}, + }, + "route.openshift.io": { + {Group: "route.openshift.io", Version: "v1", Resource: "routes"}, + }, + "security.openshift.io": { + {Group: "security.openshift.io", Version: "v1", Resource: "podsecuritypolicyreviews"}, + {Group: "security.openshift.io", Version: "v1", Resource: "podsecuritypolicyselfsubjectreviews"}, + {Group: "security.openshift.io", Version: "v1", Resource: "podsecuritypolicysubjectreviews"}, + }, + "template.openshift.io": { + {Group: "template.openshift.io", Version: "v1", Resource: "templateinstances"}, + }, } baseCRDTypes = []schema.GroupVersionResource{ @@ -181,211 +188,235 @@ var ( {Group: "metal3.io", Version: "v1alpha1", Resource: "provisionings"}, } - specialTypes = []explainExceptions{ - { - gv: schema.GroupVersion{Group: "apps.openshift.io", Version: "v1"}, - field: "deploymentconfigs.status.replicas", - pattern: `FIELD\: +replicas`, - }, - { - gv: schema.GroupVersion{Group: "route.openshift.io", Version: "v1"}, - field: "route.metadata.name", - pattern: `string`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "clusterrolebindings.userNames", - pattern: `FIELD\: +userNames`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "clusterroles.rules", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "localresourceaccessreviews", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "localsubjectaccessreviews", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "resourceaccessreviews", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "resourceaccessreviews", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "rolebindingrestrictions.spec", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "rolebindings.userNames", - pattern: `FIELD\: +userNames`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "roles.rules", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, - field: "subjectaccessreviews.scopes", - pattern: `FIELD\: +scopes`, - }, - { - gv: schema.GroupVersion{Group: "config.openshift.io", Version: "v1"}, - field: "imagecontentpolicies", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, - field: "images.dockerImageReference", - pattern: `FIELD\: +dockerImageReference.*`, - }, - { - gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, - field: "imagesignatures.imageIdentity", - pattern: `FIELD\: +imageIdentity`, - }, - { - gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, - field: "imagestreamimages.image", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, - field: "imagestreammappings.image", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, - field: "imagestreamtags.tag", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "security.internal.openshift.io", Version: "v1"}, - field: "rangeallocations.range", - pattern: `FIELD\: +range`, - }, - { - gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, - field: "oauthaccesstokens.refreshToken", - pattern: `FIELD\: +refreshToken`, - }, - { - gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, - field: "oauthauthorizetokens.redirectURI", - pattern: `FIELD\: +redirectURI`, - }, - { - gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, - field: "oauthclientauthorizations.scopes", - pattern: `FIELD\: +scopes`, - }, - { - gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, - field: "oauthclients.redirectURIs", - pattern: `FIELD\: +redirectURIs`, - }, - { - gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, - field: "useroauthaccesstokens.clientName", - pattern: `FIELD\: +clientName`, - }, - { - gv: schema.GroupVersion{Group: "project.openshift.io", Version: "v1"}, - field: "projectrequests.displayName", - pattern: `FIELD\: +displayName`, - }, - { - gv: schema.GroupVersion{Group: "security.openshift.io", Version: "v1"}, - field: "rangeallocations.range", - pattern: `FIELD\: +range`, - }, - { - gv: schema.GroupVersion{Group: "template.openshift.io", Version: "v1"}, - field: "brokertemplateinstances.spec", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "template.openshift.io", Version: "v1"}, - field: "processedtemplates.objects", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "template.openshift.io", Version: "v1"}, - field: "templates.objects", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, - field: "identities.user", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, - field: "groups.users", - pattern: `FIELD\: +users`, - }, - { - gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, - field: "useridentitymappings.user", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, - field: "users.fullName", - pattern: `FIELD\: +fullName`, - }, - { - gv: schema.GroupVersion{Group: "security.openshift.io", Version: "v1"}, - field: "securitycontextconstraints", - pattern: `FIELDS\:.*`, - }, - { - gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, - field: "consoleclidownloads.spec", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, - field: "consoleexternalloglinks.spec", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, - field: "consolelinks.spec", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, - field: "consolenotifications.spec", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1alpha1"}, - field: "consoleplugins.spec", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, - field: "consoleyamlsamples.spec", - pattern: `DESCRIPTION\:.*`, - }, - { - gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, - field: "consolequickstarts.spec", - pattern: `DESCRIPTION\:.*`, + specialTypes = map[string][]explainExceptions{ + "apps.openshift.io": { + { + gv: schema.GroupVersion{Group: "apps.openshift.io", Version: "v1"}, + field: "deploymentconfigs.status.replicas", + pattern: `FIELD\: +replicas`, + }, + }, + "route.openshift.io": { + { + gv: schema.GroupVersion{Group: "route.openshift.io", Version: "v1"}, + field: "route.metadata.name", + pattern: `string`, + }, + }, + "authorization.openshift.io": { + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "clusterrolebindings.userNames", + pattern: `FIELD\: +userNames`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "clusterroles.rules", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "localresourceaccessreviews", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "localsubjectaccessreviews", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "resourceaccessreviews", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "resourceaccessreviews", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "rolebindingrestrictions.spec", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "rolebindings.userNames", + pattern: `FIELD\: +userNames`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "roles.rules", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "subjectaccessreviews.scopes", + pattern: `FIELD\: +scopes`, + }, + }, + "config.openshift.io": { + { + gv: schema.GroupVersion{Group: "config.openshift.io", Version: "v1"}, + field: "imagecontentpolicies", + pattern: `FIELDS\:.*`, + }, + }, + "image.openshift.io": { + { + gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, + field: "images.dockerImageReference", + pattern: `FIELD\: +dockerImageReference.*`, + }, + { + gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, + field: "imagesignatures.imageIdentity", + pattern: `FIELD\: +imageIdentity`, + }, + { + gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, + field: "imagestreamimages.image", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, + field: "imagestreammappings.image", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "image.openshift.io", Version: "v1"}, + field: "imagestreamtags.tag", + pattern: `FIELDS\:.*`, + }, + }, + "security.internal.openshift.io": { + { + gv: schema.GroupVersion{Group: "security.internal.openshift.io", Version: "v1"}, + field: "rangeallocations.range", + pattern: `FIELD\: +range`, + }, + }, + "oauth.openshift.io": { + { + gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, + field: "oauthaccesstokens.refreshToken", + pattern: `FIELD\: +refreshToken`, + }, + { + gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, + field: "oauthauthorizetokens.redirectURI", + pattern: `FIELD\: +redirectURI`, + }, + { + gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, + field: "oauthclientauthorizations.scopes", + pattern: `FIELD\: +scopes`, + }, + { + gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, + field: "oauthclients.redirectURIs", + pattern: `FIELD\: +redirectURIs`, + }, + { + gv: schema.GroupVersion{Group: "oauth.openshift.io", Version: "v1"}, + field: "useroauthaccesstokens.clientName", + pattern: `FIELD\: +clientName`, + }, + }, + "project.openshift.io": { + { + gv: schema.GroupVersion{Group: "project.openshift.io", Version: "v1"}, + field: "projectrequests.displayName", + pattern: `FIELD\: +displayName`, + }, + }, + "security.openshift.io": { + { + gv: schema.GroupVersion{Group: "security.openshift.io", Version: "v1"}, + field: "rangeallocations.range", + pattern: `FIELD\: +range`, + }, + { + gv: schema.GroupVersion{Group: "security.openshift.io", Version: "v1"}, + field: "securitycontextconstraints", + pattern: `FIELDS\:.*`, + }, + }, + "template.openshift.io": { + { + gv: schema.GroupVersion{Group: "template.openshift.io", Version: "v1"}, + field: "brokertemplateinstances.spec", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "template.openshift.io", Version: "v1"}, + field: "processedtemplates.objects", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "template.openshift.io", Version: "v1"}, + field: "templates.objects", + pattern: `DESCRIPTION\:.*`, + }, + }, + "user.openshift.io": { + { + gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, + field: "identities.user", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, + field: "groups.users", + pattern: `FIELD\: +users`, + }, + { + gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, + field: "useridentitymappings.user", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "user.openshift.io", Version: "v1"}, + field: "users.fullName", + pattern: `FIELD\: +fullName`, + }, + }, + "console.openshift.io": { + { + gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, + field: "consoleclidownloads.spec", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, + field: "consoleexternalloglinks.spec", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, + field: "consolelinks.spec", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, + field: "consolenotifications.spec", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1alpha1"}, + field: "consoleplugins.spec", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, + field: "consoleyamlsamples.spec", + pattern: `DESCRIPTION\:.*`, + }, + { + gv: schema.GroupVersion{Group: "console.openshift.io", Version: "v1"}, + field: "consolequickstarts.spec", + pattern: `DESCRIPTION\:.*`, + }, }, } @@ -416,27 +447,47 @@ var ( pattern: `DESCRIPTION\:.*`, }, } -) -func getCrdTypes(oc *exutil.CLI) []schema.GroupVersionResource { - configClient := configclient.NewForConfigOrDie(oc.AdminConfig()) - clusterVersion, err := configClient.ConfigV1().ClusterVersions().Get(context.TODO(), "version", metav1.GetOptions{}) - if err != nil { - e2e.Failf("Failed to get cluster version: %v", err) + microShiftTypes = []explainExceptions{ + { + gv: schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1"}, + field: "rolebindingrestrictions.spec", + pattern: `FIELDS\:.*`, + }, + { + gv: schema.GroupVersion{Group: "security.internal.openshift.io", Version: "v1"}, + field: "rangeallocations.range", + pattern: `FIELD\: +range`, + }, + { + gv: schema.GroupVersion{Group: "security.openshift.io", Version: "v1"}, + field: "securitycontextconstraints", + pattern: `FIELDS\:.*`, + }, } +) +func getCrdTypes(oc *exutil.CLI) []schema.GroupVersionResource { crdTypes := append(baseCRDTypes, mcoTypes...) crdTypes = append(crdTypes, autoscalingTypes...) crdTypes = append(crdTypes, machineTypes...) crdTypes = append(crdTypes, additionalOperatorTypes...) - // Conditional, capability-specific types - for _, capability := range clusterVersion.Status.Capabilities.EnabledCapabilities { - switch capability { - case configv1.ClusterVersionCapabilityMarketplace: - crdTypes = append(crdTypes, marketplaceTypes...) - case configv1.ClusterVersionCapabilityBaremetal: - crdTypes = append(crdTypes, metal3Types...) + exist, err := exutil.DoesApiResourceExist(oc.AdminConfig(), "clusterversions") + o.Expect(err).NotTo(o.HaveOccurred()) + if exist { + clusterVersion, err := oc.AdminConfigClient().ConfigV1().ClusterVersions().Get(context.TODO(), "version", metav1.GetOptions{}) + if err != nil { + e2e.Failf("Failed to get cluster version: %v", err) + } + // Conditional, capability-specific types + for _, capability := range clusterVersion.Status.Capabilities.EnabledCapabilities { + switch capability { + case configv1.ClusterVersionCapabilityMarketplace: + crdTypes = append(crdTypes, marketplaceTypes...) + case configv1.ClusterVersionCapabilityBaremetal: + crdTypes = append(crdTypes, metal3Types...) + } } } @@ -466,15 +517,19 @@ var _ = g.Describe("[sig-cli] oc explain", func() { } } - for _, bt := range builtinTypes { - delete(resourceMap, bt) + for _, bts := range builtinTypes { + for _, bt := range bts { + delete(resourceMap, bt) + } } for _, ct := range crdTypes { delete(resourceMap, ct) } - for _, st := range specialTypes { - resource := strings.Split(st.field, ".") - delete(resourceMap, st.gv.WithResource(resource[0])) + for _, sts := range specialTypes { + for _, st := range sts { + resource := strings.Split(st.field, ".") + delete(resourceMap, st.gv.WithResource(resource[0])) + } } for _, snt := range specialNetworkingTypes { resource := strings.Split(snt.field, ".") @@ -496,12 +551,14 @@ var _ = g.Describe("[sig-cli] oc explain", func() { } }) - g.It("should contain spec+status for builtinTypes", func() { - for _, bt := range builtinTypes { - e2e.Logf("Checking %s...", bt) - o.Expect(verifySpecStatusExplain(oc, nil, bt)).NotTo(o.HaveOccurred()) - } - }) + for group, bts := range builtinTypes { + g.It(fmt.Sprintf("should contain spec+status for %s [apigroup:%s]", group, group), func() { + for _, bt := range bts { + e2e.Logf("Checking %s...", bt) + o.Expect(verifySpecStatusExplain(oc, nil, bt)).NotTo(o.HaveOccurred()) + } + }) + } g.It("should contain proper spec+status for CRDs [apigroup:config.openshift.io]", func() { crdClient := apiextensionsclientset.NewForConfigOrDie(oc.AdminConfig()) @@ -519,15 +576,17 @@ var _ = g.Describe("[sig-cli] oc explain", func() { } }) - g.It("should contain proper fields description for special types", func() { - for _, st := range specialTypes { - e2e.Logf("Checking %s, Field=%s...", st.gv, st.field) - resource := strings.Split(st.field, ".") - gvr := st.gv.WithResource(resource[0]) - o.Expect(verifyExplain(oc, nil, gvr, - st.pattern, st.field, fmt.Sprintf("--api-version=%s", st.gv))).NotTo(o.HaveOccurred()) - } - }) + for group, sts := range specialTypes { + g.It(fmt.Sprintf("should contain proper fields description for %s [apigroup:%s]", group, group), func() { + for _, st := range sts { + e2e.Logf("Checking %s, Field=%s...", st.gv, st.field) + resource := strings.Split(st.field, ".") + gvr := st.gv.WithResource(resource[0]) + o.Expect(verifyExplain(oc, nil, gvr, + st.pattern, st.field, fmt.Sprintf("--api-version=%s", st.gv))).NotTo(o.HaveOccurred()) + } + }) + } }) var _ = g.Describe("[sig-cli] oc explain networking types", func() { diff --git a/test/extended/cli/observe.go b/test/extended/cli/observe.go index d2f618adc84b..0e440062897b 100644 --- a/test/extended/cli/observe.go +++ b/test/extended/cli/observe.go @@ -16,7 +16,7 @@ var _ = g.Describe("[sig-cli] oc observe", func() { oc := exutil.NewCLIWithoutNamespace("oc-observe").AsAdmin() - g.It("works as expected [apigroup:config.openshift.io]", func() { + g.It("works as expected", func() { g.By("Find out the clusterIP of the kubernetes.default service") kubernetesSVC, err := oc.AdminKubeClient().CoreV1().Services("default").Get(context.Background(), "kubernetes", metav1.GetOptions{}) o.Expect(err).NotTo(o.HaveOccurred()) @@ -34,10 +34,6 @@ var _ = g.Describe("[sig-cli] oc observe", func() { o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).To(o.Or(o.ContainSubstring("Sync ended"), o.ContainSubstring("Nothing to sync, exiting immediately"))) - out, err = oc.Run("observe").Args("clusteroperators", "--once").Output() - o.Expect(err).NotTo(o.HaveOccurred()) - o.Expect(out).To(o.ContainSubstring("kube-apiserver")) - out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces").Output() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("default kubernetes")) @@ -107,4 +103,10 @@ var _ = g.Describe("[sig-cli] oc observe", func() { o.Expect(out).To(o.ContainSubstring("Sync should_be_passed")) o.Expect(os.Unsetenv("MYENV")).NotTo(o.HaveOccurred()) }) + + g.It("works as expected with cluster operators [apigroup:config.openshift.io]", func() { + out, err := oc.Run("observe").Args("clusteroperators", "--once").Output() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(out).To(o.ContainSubstring("kube-apiserver")) + }) }) diff --git a/test/extended/cli/probe.go b/test/extended/cli/probe.go index 534e5bb07bf6..f52f6f30680c 100644 --- a/test/extended/cli/probe.go +++ b/test/extended/cli/probe.go @@ -88,7 +88,7 @@ var _ = g.Describe("[sig-cli] oc probe", func() { oc.Run("delete").Args("-f", file).Execute() }) - g.It("can ensure the probe command is functioning as expected on deploymentconfigs", func() { + g.It("can ensure the probe command is functioning as expected on deploymentconfigs [apigroup:apps.openshift.io]", func() { g.By("creating a test-deployment-config deploymentconfig") err := oc.Run("create").Args("-f", deploymentConfig).Execute() o.Expect(err).NotTo(o.HaveOccurred()) diff --git a/test/extended/cli/rsh.go b/test/extended/cli/rsh.go index 5d513f4a818b..0dc961a2d171 100644 --- a/test/extended/cli/rsh.go +++ b/test/extended/cli/rsh.go @@ -1,11 +1,16 @@ package cli import ( + "context" "time" g "github.com/onsi/ginkgo/v2" o "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8simage "k8s.io/kubernetes/test/utils/image" admissionapi "k8s.io/pod-security-admission/api" exutil "github.com/openshift/origin/test/extended/util" @@ -15,16 +20,16 @@ var _ = g.Describe("[sig-cli] oc rsh", func() { defer g.GinkgoRecover() var ( - oc = exutil.NewCLIWithPodSecurityLevel("oc-rsh", admissionapi.LevelBaseline) - multiContainersFixture = exutil.FixturePath("testdata", "cli", "pod-with-two-containers.yaml") - podsLabel = exutil.ParseLabelsOrDie("name=hello-centos") + oc = exutil.NewCLIWithPodSecurityLevel("oc-rsh", admissionapi.LevelBaseline) + podsLabel = exutil.ParseLabelsOrDie("name=hello-busybox") ) g.Describe("specific flags", func() { g.It("should work well when access to a remote shell", func() { namespace := oc.Namespace() g.By("Creating pods with multi containers") - err := oc.Run("create").Args("-f", multiContainersFixture).Execute() + + _, err := oc.KubeClient().CoreV1().Pods(namespace).Create(context.Background(), newPodWithTwoContainers(), metav1.CreateOptions{}) o.Expect(err).NotTo(o.HaveOccurred()) g.By("expecting the pod to be running") @@ -34,11 +39,56 @@ var _ = g.Describe("[sig-cli] oc rsh", func() { g.By("running the rsh command without specify container name") out, err := oc.Run("rsh").Args(pods[0], "mkdir", "/tmp/test1").Output() o.Expect(err).NotTo(o.HaveOccurred()) - o.Expect(out).To(o.MatchRegexp(`Default.*container.*hello-centos`)) + o.Expect(out).To(o.MatchRegexp(`Default.*container.*hello-busybox`)) g.By("running the rsh command with specify container name and shell") - _, err = oc.Run("rsh").Args("--container=hello-centos-2", "--shell=/bin/sh", pods[0], "mkdir", "/tmp/test3").Output() + _, err = oc.Run("rsh").Args("--container=hello-busybox-2", "--shell=/bin/sh", pods[0], "mkdir", "/tmp/test3").Output() o.Expect(err).NotTo(o.HaveOccurred()) }) }) }) + +func newPodWithTwoContainers() *corev1.Pod { + return &corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Pod", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "doublecontainers", + Labels: map[string]string{ + "name": "hello-busybox", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "hello-busybox", + Image: k8simage.GetE2EImage(k8simage.BusyBox), + Command: []string{"/bin/sleep", "1h"}, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("256Mi"), + }, + }, + TerminationMessagePath: "/dev/termination-log-1", + ImagePullPolicy: corev1.PullIfNotPresent, + }, + { + Name: "hello-busybox-2", + Image: k8simage.GetE2EImage(k8simage.BusyBox), + Command: []string{"/bin/sleep", "1h"}, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("256Mi"), + }, + }, + TerminationMessagePath: "/dev/termination-log-2", + ImagePullPolicy: corev1.PullIfNotPresent, + }, + }, + RestartPolicy: corev1.RestartPolicyAlways, + DNSPolicy: corev1.DNSClusterFirst, + }, + } +} diff --git a/test/extended/idling/idling.go b/test/extended/idling/idling.go index 937d49eead6d..eee187cf759e 100644 --- a/test/extended/idling/idling.go +++ b/test/extended/idling/idling.go @@ -216,7 +216,7 @@ var _ = g.Describe("[sig-network-edge][Feature:Idling]", func() { }) g.Describe("Idling", func() { - g.Context("with a single service and DeploymentConfig", func() { + g.Context("with a single service and DeploymentConfig [apigroup:route.openshift.io]", func() { g.BeforeEach(func() { framework.BeforeEach() fixture = echoServerFixture @@ -239,7 +239,7 @@ var _ = g.Describe("[sig-network-edge][Feature:Idling]", func() { }) }) - g.Describe("Unidling", func() { + g.Describe("Unidling [apigroup:apps.openshift.io][apigroup:route.openshift.io]", func() { g.BeforeEach(func() { framework.BeforeEach() fixture = echoServerFixture diff --git a/test/extended/networking/multus.go b/test/extended/networking/multus.go index 68f6b6a2ce1d..a1f5e8ca854b 100644 --- a/test/extended/networking/multus.go +++ b/test/extended/networking/multus.go @@ -24,7 +24,7 @@ var _ = g.Describe("[sig-network][Feature:Multus]", func() { // Multus is already installed on origin. These tests aims to verify the integrity of the installation. - g.It("should use multus to create net1 device from network-attachment-definition", func() { + g.It("should use multus to create net1 device from network-attachment-definition [apigroup:k8s.cni.cncf.io]", func() { var err error ns = f.Namespace.Name diff --git a/test/extended/networking/services.go b/test/extended/networking/services.go index f587be4c8c01..1c8236915b53 100644 --- a/test/extended/networking/services.go +++ b/test/extended/networking/services.go @@ -88,7 +88,7 @@ var _ = Describe("[sig-network] services", func() { var retryInterval = 1 * time.Minute InIPv4ClusterContext(oc, func() { - It("ensures external ip policy is configured correctly on the cluster [Serial]", func() { + It("ensures external ip policy is configured correctly on the cluster [apigroup:config.openshift.io] [Serial]", func() { namespace := oc.Namespace() adminConfigClient := oc.AdminConfigClient() k8sClient := oc.KubeClient() @@ -165,7 +165,7 @@ var _ = Describe("[sig-network] services", func() { }) InBareMetalIPv4ClusterContext(oc, func() { - It("ensures external auto assign cidr is configured correctly on the cluster [Serial]", func() { + It("ensures external auto assign cidr is configured correctly on the cluster [apigroup:config.openshift.io] [Serial]", func() { namespace := oc.Namespace() adminConfigClient := oc.AdminConfigClient() k8sClient := oc.KubeClient() diff --git a/test/extended/networking/tuning.go b/test/extended/networking/tuning.go index 12988b15eae6..24aea0a73d32 100644 --- a/test/extended/networking/tuning.go +++ b/test/extended/networking/tuning.go @@ -60,7 +60,7 @@ var _ = g.Describe("[sig-network][Feature:tuning]", func() { oc := exutil.NewCLIWithPodSecurityLevel("tuning", admissionapi.LevelPrivileged) f := oc.KubeFramework() - g.It("pod should start with all sysctl on whitelist", func() { + g.It("pod should start with all sysctl on whitelist [apigroup:k8s.cni.cncf.io]", func() { namespace := f.Namespace.Name sysctls := map[string]string{} for _, sysctl := range whitelistedSysctls { @@ -78,7 +78,7 @@ var _ = g.Describe("[sig-network][Feature:tuning]", func() { o.Expect(result).To(o.Equal(sysctl.Value), "incorrect sysctl value") } }) - g.DescribeTable("pod should not start for sysctls not on whitelist", func(sysctl, value string) { + g.DescribeTable("pod should not start for sysctls not on whitelist [apigroup:k8s.cni.cncf.io]", func(sysctl, value string) { namespace := f.Namespace.Name tuningNADName := "tuningnadwithdisallowedsysctls" err := createTuningNAD(oc.AdminConfig(), namespace, tuningNADName, map[string]string{sysctl: value}) @@ -104,7 +104,7 @@ var _ = g.Describe("[sig-network][Feature:tuning]", func() { g.Entry("net.ipv4.conf.IFNAME.arp_filter", "net.ipv4.conf.IFNAME.arp_filter", "1"), ) - g.It("pod sysctls should not affect node", func() { + g.It("pod sysctls should not affect node [apigroup:k8s.cni.cncf.io]", func() { namespace := f.Namespace.Name g.By("creating a preexisting pod to check host sysctl") nodePod := frameworkpod.CreateExecPodOrFail(f.ClientSet, f.Namespace.Name, "nodeaccess-pod-", func(pod *kapiv1.Pod) { @@ -161,7 +161,7 @@ var _ = g.Describe("[sig-network][Feature:tuning]", func() { o.Expect(hostSysctlValue).Should(o.Equal(hostSysctlValue2)) }) - g.It("pod sysctl should not affect existing pods", func() { + g.It("pod sysctl should not affect existing pods [apigroup:k8s.cni.cncf.io]", func() { namespace := f.Namespace.Name path := fmt.Sprintf(sysctlPath, "net1") err := createNAD(oc.AdminConfig(), namespace, baseNAD) @@ -190,7 +190,7 @@ var _ = g.Describe("[sig-network][Feature:tuning]", func() { o.Expect(podOutputBeforeSysctlAplied).Should(o.Equal(podOutputAfterSysctlAplied)) }) - g.It("pod sysctl should not affect newly created pods", func() { + g.It("pod sysctl should not affect newly created pods [apigroup:k8s.cni.cncf.io]", func() { namespace := f.Namespace.Name path := fmt.Sprintf(sysctlPath, "net1") diff --git a/test/extended/networking/whereabouts.go b/test/extended/networking/whereabouts.go index 332ea060f9d6..2b14fb45f6a4 100644 --- a/test/extended/networking/whereabouts.go +++ b/test/extended/networking/whereabouts.go @@ -24,7 +24,7 @@ var _ = g.Describe("[sig-network][Feature:Whereabouts]", func() { // Whereabouts is already installed in Origin. These tests aims to verify the integrity of the installation. - g.It("should use whereabouts net-attach-def to limit IP ranges for newly created pods", func() { + g.It("should use whereabouts net-attach-def to limit IP ranges for newly created pods [apigroup:k8s.cni.cncf.io]", func() { var err error f := oc.KubeFramework() @@ -109,7 +109,7 @@ var _ = g.Describe("[sig-network][Feature:Whereabouts]", func() { }) - g.It("should assign unique IP addresses to each pod in the event of a race condition case", func() { + g.It("should assign unique IP addresses to each pod in the event of a race condition case [apigroup:k8s.cni.cncf.io]", func() { // steps for the test // 1. create sleepy pod // 2. create awake pod diff --git a/test/extended/operators/clusteroperators.go b/test/extended/operators/clusteroperators.go index 6897649b9014..c03079758acc 100644 --- a/test/extended/operators/clusteroperators.go +++ b/test/extended/operators/clusteroperators.go @@ -11,10 +11,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kube-openapi/pkg/util/sets" - e2e "k8s.io/kubernetes/test/e2e/framework" config "github.com/openshift/api/config/v1" - configclient "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" exutil "github.com/openshift/origin/test/extended/util" ) @@ -45,12 +43,10 @@ var _ = g.Describe("[sig-arch] ClusterOperators [apigroup:config.openshift.io]", "support", ) + oc := exutil.NewCLIWithoutNamespace("clusteroperators") + g.BeforeEach(func() { - kubeConfig, err := e2e.LoadConfig() - o.Expect(err).ToNot(o.HaveOccurred()) - configClient, err := configclient.NewForConfig(kubeConfig) - o.Expect(err).ToNot(o.HaveOccurred()) - clusterOperatorsList, err := configClient.ClusterOperators().List(context.Background(), metav1.ListOptions{}) + clusterOperatorsList, err := oc.AdminConfigClient().ConfigV1().ClusterOperators().List(context.Background(), metav1.ListOptions{}) o.Expect(err).ToNot(o.HaveOccurred()) clusterOperators = clusterOperatorsList.Items }) diff --git a/test/extended/operators/images.go b/test/extended/operators/images.go index f5f3de096758..1e3929db6681 100644 --- a/test/extended/operators/images.go +++ b/test/extended/operators/images.go @@ -19,7 +19,7 @@ import ( var _ = Describe("[sig-arch] Managed cluster", func() { oc := exutil.NewCLIWithoutNamespace("operators") - It("should ensure pods use downstream images from our release image with proper ImagePullPolicy", func() { + It("should ensure pods use downstream images from our release image with proper ImagePullPolicy [apigroup:config.openshift.io]", func() { imagePullSecret, err := oc.KubeFramework().ClientSet.CoreV1().Secrets("openshift-config").Get(context.Background(), "pull-secret", metav1.GetOptions{}) if err != nil { e2e.Failf("unable to get pull secret for cluster: %v", err) diff --git a/test/extended/security/scc.go b/test/extended/security/scc.go index 7b164cfc9812..ceb3a855e604 100644 --- a/test/extended/security/scc.go +++ b/test/extended/security/scc.go @@ -2,19 +2,26 @@ package security import ( "context" + "fmt" "strings" + "time" g "github.com/onsi/ginkgo/v2" o "github.com/onsi/gomega" + authenticationv1 "k8s.io/api/authentication/v1" kubeauthorizationv1 "k8s.io/api/authorization/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" kapierror "k8s.io/apimachinery/pkg/api/errors" + kapierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" "k8s.io/kubernetes/test/e2e/framework" + e2e "k8s.io/kubernetes/test/e2e/framework" admissionapi "k8s.io/pod-security-admission/api" securityv1 "github.com/openshift/api/security/v1" @@ -33,58 +40,71 @@ var _ = g.Describe("[sig-auth][Feature:SecurityContextConstraints] ", func() { g.It("TestPodUpdateSCCEnforcement [apigroup:user.openshift.io][apigroup:authorization.openshift.io]", func() { t := g.GinkgoT() - clusterAdminKubeClientset := oc.AdminKubeClient() - projectName := oc.Namespace() haroldUser := oc.CreateUser("harold-").Name haroldClientConfig := oc.GetClientConfigForUser(haroldUser) haroldKubeClient := kubernetes.NewForConfigOrDie(haroldClientConfig) authorization.AddUserAdminToProject(oc, projectName, haroldUser) - // so cluster-admin can create privileged pods, but harold cannot. This means that harold should not be able - // to update the privileged pods either, even if he lies about its privileged nature - privilegedPod := getPrivilegedPod("unsafe") - - if _, err := haroldKubeClient.CoreV1().Pods(projectName).Create(ctx, privilegedPod, metav1.CreateOptions{}); !isForbiddenBySCC(err) { - t.Fatalf("missing forbidden: %v", err) - } - - actualPod, err := clusterAdminKubeClientset.CoreV1().Pods(projectName).Create(ctx, privilegedPod, metav1.CreateOptions{}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } + RunTestPodUpdateSCCEnforcement(ctx, haroldKubeClient, oc.AdminKubeClient(), projectName, t) + }) - actualPod.Spec.Containers[0].Image = "something-nefarious" - if _, err := haroldKubeClient.CoreV1().Pods(projectName).Update(ctx, actualPod, metav1.UpdateOptions{}); !isForbiddenBySCC(err) { - t.Fatalf("missing forbidden: %v", err) - } + g.It("TestPodUpdateSCCEnforcement with service account", func() { + t := g.GinkgoT() - // try to connect to /exec subresource as harold - haroldCorev1Rest := haroldKubeClient.CoreV1().RESTClient() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - result := &metav1.Status{} - err = haroldCorev1Rest.Post(). - Resource("pods"). - Namespace(projectName). - Name(actualPod.Name). - SubResource("exec"). - Param("container", "first"). - Do(ctx). - Into(result) - if !isForbiddenBySCCExecRestrictions(err) { - t.Fatalf("missing forbidden by SCCExecRestrictions: %v", err) - } + projectName := oc.Namespace() + sa := createServiceAccount(ctx, oc, projectName) + createPodAdminRoleOrDie(ctx, oc, sa) + restrictedClient, _ := createClientFromServiceAccount(oc, sa) - // try to lie about the privileged nature - actualPod.Spec.HostPID = false - if _, err := haroldKubeClient.CoreV1().Pods(projectName).Update(context.Background(), actualPod, metav1.UpdateOptions{}); err == nil { - t.Fatalf("missing error: %v", err) - } + RunTestPodUpdateSCCEnforcement(ctx, restrictedClient, oc.AdminKubeClient(), projectName, t) }) }) +func RunTestPodUpdateSCCEnforcement(ctx context.Context, restrictedClient, clusterAdminKubeClientset kubernetes.Interface, namespace string, t g.GinkgoTInterface) { + // so cluster-admin can create privileged pods, but harold cannot. This means that harold should not be able + // to update the privileged pods either, even if he lies about its privileged nature + privilegedPod := getPrivilegedPod("unsafe") + + if _, err := restrictedClient.CoreV1().Pods(namespace).Create(ctx, privilegedPod, metav1.CreateOptions{}); !isForbiddenBySCC(err) { + t.Fatalf("missing forbidden: %v", err) + } + + actualPod, err := clusterAdminKubeClientset.CoreV1().Pods(namespace).Create(ctx, privilegedPod, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + actualPod.Spec.Containers[0].Image = "something-nefarious" + if _, err := restrictedClient.CoreV1().Pods(namespace).Update(ctx, actualPod, metav1.UpdateOptions{}); !isForbiddenBySCC(err) { + t.Fatalf("missing forbidden: %v", err) + } + + // try to connect to /exec subresource as harold + haroldCorev1Rest := restrictedClient.CoreV1().RESTClient() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + result := &metav1.Status{} + err = haroldCorev1Rest.Post(). + Resource("pods"). + Namespace(namespace). + Name(actualPod.Name). + SubResource("exec"). + Param("container", "first"). + Do(ctx). + Into(result) + if !isForbiddenBySCCExecRestrictions(err) { + t.Fatalf("missing forbidden by SCCExecRestrictions: %v", err) + } + + // try to lie about the privileged nature + actualPod.Spec.HostPID = false + if _, err := restrictedClient.CoreV1().Pods(namespace).Update(context.Background(), actualPod, metav1.UpdateOptions{}); err == nil { + t.Fatalf("missing error: %v", err) + } +} + var _ = g.Describe("[sig-auth][Feature:SecurityContextConstraints] ", func() { ctx := context.Background() @@ -102,24 +122,7 @@ var _ = g.Describe("[sig-auth][Feature:SecurityContextConstraints] ", func() { user1 := oc.CreateUser("user1-").Name user2 := oc.CreateUser("user2-").Name - clusterRole := "all-scc-" + oc.Namespace() - rule := rbacv1helpers.NewRule("use").Groups("security.openshift.io").Resources("securitycontextconstraints").RuleOrDie() - - // set a up cluster role that allows access to all SCCs - if _, err := clusterAdminKubeClientset.RbacV1().ClusterRoles().Create( - ctx, - &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{Name: clusterRole}, - Rules: []rbacv1.PolicyRule{rule}, - }, - metav1.CreateOptions{}, - ); err != nil { - t.Fatal(err) - } - oc.AddExplicitResourceToDelete(rbacv1.SchemeGroupVersion.WithResource("clusterroles"), "", clusterRole) - // set up 2 projects for 2 users - authorization.AddUserAdminToProject(oc, project1, user1) user1Config := oc.GetClientConfigForUser(user1) user1Client := kubernetes.NewForConfigOrDie(user1Config) @@ -130,140 +133,231 @@ var _ = g.Describe("[sig-auth][Feature:SecurityContextConstraints] ", func() { user2Client := kubernetes.NewForConfigOrDie(user2Config) user2SecurityClient := securityv1client.NewForConfigOrDie(user2Config) - createOpts := metav1.CreateOptions{} + RunTestAllowedSCCViaRBAC( + ctx, + oc, + clusterAdminKubeClientset, user1Client, user2Client, + user1SecurityClient, user2SecurityClient, + project1, project2, + rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1helpers.GroupName, Name: user1}, + rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1helpers.GroupName, Name: user2}, + t, + ) + }) - // user1 cannot make a privileged pod - if _, err := user1Client.CoreV1().Pods(project1).Create(ctx, getPrivilegedPod("test1"), createOpts); !isForbiddenBySCC(err) { - t.Fatalf("missing forbidden for user1: %v", err) - } + g.It("TestAllowedSCCViaRBAC with service account [apigroup:security.openshift.io]", func() { + t := g.GinkgoT() - // user2 cannot make a privileged pod - if _, err := user2Client.CoreV1().Pods(project2).Create(ctx, getPrivilegedPod("test2"), createOpts); !isForbiddenBySCC(err) { - t.Fatalf("missing forbidden for user2: %v", err) - } + clusterAdminKubeClientset := oc.AdminKubeClient() - // this should allow user1 to make a privileged pod in project1 - rb := rbacv1helpers.NewRoleBindingForClusterRole(clusterRole, project1).Users(user1).BindingOrDie() - if _, err := clusterAdminKubeClientset.RbacV1().RoleBindings(project1).Create(ctx, &rb, createOpts); err != nil { - t.Fatal(err) + newNamespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-namespace-2", oc.Namespace()), + }, } + _, err := oc.AdminKubeClient().CoreV1().Namespaces().Create(context.Background(), newNamespace, metav1.CreateOptions{}) + o.Expect(err).NotTo(o.HaveOccurred()) + oc.AddExplicitResourceToDelete(corev1.SchemeGroupVersion.WithResource("namespaces"), "", newNamespace.Name) - // this should allow user1 to make pods in project2 - rbEditUser1Project2 := rbacv1helpers.NewRoleBindingForClusterRole("edit", project2).Users(user1).BindingOrDie() - if _, err := clusterAdminKubeClientset.RbacV1().RoleBindings(project2).Create(ctx, &rbEditUser1Project2, createOpts); err != nil { - t.Fatal(err) - } + namespace1 := oc.Namespace() + namespace2 := newNamespace.Name - // this should allow user2 to make pods in project1 - rbEditUser2Project1 := rbacv1helpers.NewRoleBindingForClusterRole("edit", project1).Users(user2).BindingOrDie() - if _, err := clusterAdminKubeClientset.RbacV1().RoleBindings(project1).Create(ctx, &rbEditUser2Project1, createOpts); err != nil { - t.Fatal(err) - } + sa1 := createServiceAccount(ctx, oc, namespace1) + createPodAdminRoleOrDie(ctx, oc, sa1) + createPodSecurityPolicySelfSubjectReviewsRoleBindingOrDie(ctx, oc, sa1) - // this should allow user2 to make a privileged pod in all projects - crb := rbacv1helpers.NewClusterBinding(clusterRole).Users(user2).BindingOrDie() - if _, err := clusterAdminKubeClientset.RbacV1().ClusterRoleBindings().Create(ctx, &crb, createOpts); err != nil { - t.Fatal(err) - } - oc.AddExplicitResourceToDelete(rbacv1.SchemeGroupVersion.WithResource("clusterrolebindings"), "", crb.Name) - - // wait for RBAC to catch up to user1 role binding for SCC - if err := oc.WaitForAccessAllowed(&kubeauthorizationv1.SelfSubjectAccessReview{ - Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ - Namespace: project1, - Verb: rule.Verbs[0], - Group: rule.APIGroups[0], - Resource: rule.Resources[0], - }, + sa2 := createServiceAccount(ctx, oc, namespace2) + createPodAdminRoleOrDie(ctx, oc, sa2) + createPodSecurityPolicySelfSubjectReviewsRoleBindingOrDie(ctx, oc, sa2) + + // set up 2 namespaces for 2 service accounts + sa1Client, sa1SecurityClient := createClientFromServiceAccount(oc, sa1) + sa2Client, sa2SecurityClient := createClientFromServiceAccount(oc, sa2) + + RunTestAllowedSCCViaRBAC( + ctx, + oc, + clusterAdminKubeClientset, sa1Client, sa2Client, + sa1SecurityClient, sa2SecurityClient, + namespace1, namespace2, + rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: sa1.Namespace, Name: sa1.Name}, + rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: sa2.Namespace, Name: sa2.Name}, + t, + ) + }) +}) + +func addSubjectsToClusterRoleBindingBuilder(builder *rbacv1helpers.ClusterRoleBindingBuilder, subjects ...rbacv1.Subject) *rbacv1helpers.ClusterRoleBindingBuilder { + for _, subject := range subjects { + builder.ClusterRoleBinding.Subjects = append(builder.ClusterRoleBinding.Subjects, subject) + } + return builder +} + +func addSubjectsToRoleBindingBuilder(builder *rbacv1helpers.RoleBindingBuilder, subjects ...rbacv1.Subject) *rbacv1helpers.RoleBindingBuilder { + for _, subject := range subjects { + builder.RoleBinding.Subjects = append(builder.RoleBinding.Subjects, subject) + } + return builder +} + +func RunTestAllowedSCCViaRBAC( + ctx context.Context, + oc *exutil.CLI, + clusterAdminKubeClientset, clientset1, clientset2 kubernetes.Interface, + securityClientset1, securityClientset2 *securityv1client.SecurityV1Client, + namespace1, namespace2 string, + subject1, subject2 rbacv1.Subject, + t g.GinkgoTInterface, +) { + clusterRole := "all-scc-" + namespace1 + rule := rbacv1helpers.NewRule("use").Groups("security.openshift.io").Resources("securitycontextconstraints").RuleOrDie() + + // set a up cluster role that allows access to all SCCs + _, err := clusterAdminKubeClientset.RbacV1().ClusterRoles().Create( + ctx, + &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{Name: clusterRole}, + Rules: []rbacv1.PolicyRule{rule}, + }, + metav1.CreateOptions{}, + ) + o.Expect(err).NotTo(o.HaveOccurred()) + oc.AddExplicitResourceToDelete(rbacv1.SchemeGroupVersion.WithResource("clusterroles"), "", clusterRole) + + createOpts := metav1.CreateOptions{} + + // subject1 cannot make a privileged pod + if _, err := clientset1.CoreV1().Pods(namespace1).Create(ctx, getPrivilegedPod("test1"), createOpts); !isForbiddenBySCC(err) { + t.Fatalf("missing forbidden for serviceaccount1: %v", err) + } + + // subject2 cannot make a privileged pod + if _, err := clientset2.CoreV1().Pods(namespace2).Create(ctx, getPrivilegedPod("test2"), createOpts); !isForbiddenBySCC(err) { + t.Fatalf("missing forbidden for serviceaccount2: %v", err) + } + + // this should allow subject1 to make a privileged pod in namespace1 + rb := addSubjectsToRoleBindingBuilder(rbacv1helpers.NewRoleBindingForClusterRole(clusterRole, namespace1), subject1).BindingOrDie() + if _, err := clusterAdminKubeClientset.RbacV1().RoleBindings(namespace1).Create(ctx, &rb, createOpts); err != nil { + t.Fatal(err) + } + + // this should allow subject1 to make pods in namespace2 + rbEditUser1Project2 := addSubjectsToRoleBindingBuilder(rbacv1helpers.NewRoleBindingForClusterRole("edit", namespace2), subject1).BindingOrDie() + if _, err := clusterAdminKubeClientset.RbacV1().RoleBindings(namespace2).Create(ctx, &rbEditUser1Project2, createOpts); err != nil { + t.Fatal(err) + } + + // this should allow subject2 to make pods in namespace1 + rbEditUser2Project1 := addSubjectsToRoleBindingBuilder(rbacv1helpers.NewRoleBindingForClusterRole("edit", namespace1), subject2).BindingOrDie() + if _, err := clusterAdminKubeClientset.RbacV1().RoleBindings(namespace1).Create(ctx, &rbEditUser2Project1, createOpts); err != nil { + t.Fatal(err) + } + + // this should allow subject2 to make a privileged pod in all namespaces + crb := addSubjectsToClusterRoleBindingBuilder(rbacv1helpers.NewClusterBinding(clusterRole), subject2).BindingOrDie() + if _, err := clusterAdminKubeClientset.RbacV1().ClusterRoleBindings().Create(ctx, &crb, createOpts); err != nil { + t.Fatal(err) + } + oc.AddExplicitResourceToDelete(rbacv1.SchemeGroupVersion.WithResource("clusterrolebindings"), "", crb.Name) + + // wait for RBAC to catch up to subject1 role binding for SCC + if err := exutil.WaitForAccess(clientset1, true, &kubeauthorizationv1.SelfSubjectAccessReview{ + Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ + Namespace: namespace1, + Verb: rule.Verbs[0], + Group: rule.APIGroups[0], + Resource: rule.Resources[0], }, - }, user1); err != nil { - t.Fatal(err) - } + }, + }); err != nil { + t.Fatal(err) + } - // wait for RBAC to catch up to user1 role binding for edit - if err := oc.WaitForAccessAllowed(&kubeauthorizationv1.SelfSubjectAccessReview{ - Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ - Namespace: project2, - Verb: "create", - Group: "", - Resource: "pods", - }, + // wait for RBAC to catch up to subject1 role binding for edit + if err := exutil.WaitForAccess(clientset1, true, &kubeauthorizationv1.SelfSubjectAccessReview{ + Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ + Namespace: namespace2, + Verb: "create", + Group: "", + Resource: "pods", }, - }, user1); err != nil { - t.Fatal(err) - } + }, + }); err != nil { + t.Fatal(err) + } - // wait for RBAC to catch up to user2 role binding - if err := oc.WaitForAccessAllowed(&kubeauthorizationv1.SelfSubjectAccessReview{ - Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ - Namespace: project1, - Verb: "create", - Group: "", - Resource: "pods", - }, + // wait for RBAC to catch up to subject2 role binding + if err := exutil.WaitForAccess(clientset2, true, &kubeauthorizationv1.SelfSubjectAccessReview{ + Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ + Namespace: namespace1, + Verb: "create", + Group: "", + Resource: "pods", }, - }, user2); err != nil { - t.Fatal(err) - } + }, + }); err != nil { + t.Fatal(err) + } - // wait for RBAC to catch up to user2 cluster role binding - if err := oc.WaitForAccessAllowed(&kubeauthorizationv1.SelfSubjectAccessReview{ - Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ - Namespace: project2, - Verb: rule.Verbs[0], - Group: rule.APIGroups[0], - Resource: rule.Resources[0], - }, + // wait for RBAC to catch up to subject2 cluster role binding + if err := exutil.WaitForAccess(clientset2, true, &kubeauthorizationv1.SelfSubjectAccessReview{ + Spec: kubeauthorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &kubeauthorizationv1.ResourceAttributes{ + Namespace: namespace2, + Verb: rule.Verbs[0], + Group: rule.APIGroups[0], + Resource: rule.Resources[0], }, - }, user2); err != nil { - t.Fatal(err) - } + }, + }); err != nil { + t.Fatal(err) + } - // user1 can make a privileged pod in project1 - if _, err := user1Client.CoreV1().Pods(project1).Create(ctx, getPrivilegedPod("test3"), createOpts); err != nil { - t.Fatalf("user1 failed to create pod in project1 via local binding: %v", err) - } + // subject1 can make a privileged pod in namespace1 + if _, err := clientset1.CoreV1().Pods(namespace1).Create(ctx, getPrivilegedPod("test3"), createOpts); err != nil { + t.Fatalf("subject1 failed to create pod in namespace1 via local binding: %v", err) + } - // user1 cannot make a privileged pod in project2 - if _, err := user1Client.CoreV1().Pods(project2).Create(ctx, getPrivilegedPod("test4"), createOpts); !isForbiddenBySCC(err) { - t.Fatalf("missing forbidden for user1 in project2: %v", err) - } + // subject1 cannot make a privileged pod in namespace2 + if _, err := clientset1.CoreV1().Pods(namespace2).Create(ctx, getPrivilegedPod("test4"), createOpts); !isForbiddenBySCC(err) { + t.Fatalf("missing forbidden for serviceaccount1 in namespace2: %v", err) + } - // user2 can make a privileged pod in project1 - if _, err := user2Client.CoreV1().Pods(project1).Create(ctx, getPrivilegedPod("test5"), createOpts); err != nil { - t.Fatalf("user2 failed to create pod in project1 via cluster binding: %v", err) - } + // subject2 can make a privileged pod in namespace1 + if _, err := clientset2.CoreV1().Pods(namespace1).Create(ctx, getPrivilegedPod("test5"), createOpts); err != nil { + t.Fatalf("subject2 failed to create pod in namespace1 via cluster binding: %v", err) + } - // user2 can make a privileged pod in project2 - if _, err := user2Client.CoreV1().Pods(project2).Create(ctx, getPrivilegedPod("test6"), createOpts); err != nil { - t.Fatalf("user2 failed to create pod in project2 via cluster binding: %v", err) - } + // subject2 can make a privileged pod in namespace2 + if _, err := clientset2.CoreV1().Pods(namespace2).Create(ctx, getPrivilegedPod("test6"), createOpts); err != nil { + t.Fatalf("subject2 failed to create pod in namespace2 via cluster binding: %v", err) + } - // make sure PSP self subject review works since that is based by the same SCC logic but has different wiring + // make sure PSP self subject review works since that is based by the same SCC logic but has different wiring - // user1 can make a privileged pod in project1 - user1PSPReview, err := user1SecurityClient.PodSecurityPolicySelfSubjectReviews(project1).Create(ctx, runAsRootPSPSSR(), createOpts) - if err != nil { - t.Fatal(err) - } - if allowedBy := user1PSPReview.Status.AllowedBy; allowedBy == nil || allowedBy.Name != "anyuid" { - t.Fatalf("user1 failed PSP SSR in project1: %v", allowedBy) - } + // subject1 can make a privileged pod in namespace1 + subject1PSPReview, err := securityClientset1.PodSecurityPolicySelfSubjectReviews(namespace1).Create(ctx, runAsRootPSPSSR(), createOpts) + if err != nil { + t.Fatal(err) + } + if allowedBy := subject1PSPReview.Status.AllowedBy; allowedBy == nil || allowedBy.Name != "anyuid" { + t.Fatalf("subject1 failed PSP SSR in namespace1: %v", allowedBy) + } - // user2 can make a privileged pod in project2 - user2PSPReview, err := user2SecurityClient.PodSecurityPolicySelfSubjectReviews(project2).Create(ctx, runAsRootPSPSSR(), createOpts) - if err != nil { - t.Fatal(err) - } - if allowedBy := user2PSPReview.Status.AllowedBy; allowedBy == nil || allowedBy.Name != "anyuid" { - t.Fatalf("user2 failed PSP SSR in project2: %v", allowedBy) - } - }) -}) + // subject2 can make a privileged pod in namespace2 + subject2PSPReview, err := securityClientset2.PodSecurityPolicySelfSubjectReviews(namespace2).Create(ctx, runAsRootPSPSSR(), createOpts) + if err != nil { + t.Fatal(err) + } + if allowedBy := subject2PSPReview.Status.AllowedBy; allowedBy == nil || allowedBy.Name != "anyuid" { + t.Fatalf("subject2 failed PSP SSR in namespace2: %v", allowedBy) + } +} var _ = g.Describe("[sig-auth][Feature:SecurityContextConstraints] ", func() { defer g.GinkgoRecover() @@ -342,3 +436,111 @@ func runAsRootPSPSSR() *securityv1.PodSecurityPolicySelfSubjectReview { }, } } + +func createPodAdminRoleOrDie(ctx context.Context, oc *exutil.CLI, sa *corev1.ServiceAccount) { + framework.Logf("Creating role") + rule := rbacv1helpers.NewRule("create", "update").Groups("").Resources("pods", "pods/exec").RuleOrDie() + _, err := oc.AdminKubeClient().RbacV1().Roles(sa.Namespace).Create( + ctx, + &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: "podadmin"}, + Rules: []rbacv1.PolicyRule{rule}, + }, + metav1.CreateOptions{}, + ) + o.Expect(err).NotTo(o.HaveOccurred()) + + framework.Logf("Creating rolebinding") + _, err = oc.AdminKubeClient().RbacV1().RoleBindings(sa.Namespace).Create(ctx, &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: sa.Namespace, + GenerateName: "podadmin-", + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: sa.Name, + }, + }, + RoleRef: rbacv1.RoleRef{ + Kind: "Role", + Name: "podadmin", + }, + }, metav1.CreateOptions{}) + o.Expect(err).NotTo(o.HaveOccurred()) +} + +func createServiceAccount(ctx context.Context, oc *exutil.CLI, namespace string) *corev1.ServiceAccount { + framework.Logf("Creating ServiceAccount") + sa, err := oc.AdminKubeClient().CoreV1().ServiceAccounts(namespace).Create(ctx, &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{GenerateName: "test-sa-"}}, metav1.CreateOptions{}) + o.Expect(err).NotTo(o.HaveOccurred()) + + framework.Logf("Waiting for ServiceAccount %q to be provisioned...", sa.Name) + err = wait.Poll(100*time.Millisecond, 3*time.Minute, func() (bool, error) { + _, err := oc.AdminKubeClient().CoreV1().ServiceAccounts(namespace).Get(context.Background(), sa.Name, metav1.GetOptions{}) + if err != nil { + // If we can't access the service accounts, let's wait till the controller + // create it. + if kapierrs.IsNotFound(err) || kapierrs.IsForbidden(err) { + e2e.Logf("Waiting for service account %q to be available: %v (will retry) ...", sa.Name, err) + return false, nil + } + return false, fmt.Errorf("Failed to get service account %q: %v", sa.Name, err) + } + return true, nil + }) + + o.Expect(err).NotTo(o.HaveOccurred()) + + return sa +} + +func createPodSecurityPolicySelfSubjectReviewsRoleBindingOrDie(ctx context.Context, oc *exutil.CLI, sa *corev1.ServiceAccount) { + framework.Logf("Creating podsecuritypolicyselfsubjectreviews role") + rule := rbacv1helpers.NewRule("create").Groups("security.openshift.io").Resources("podsecuritypolicyselfsubjectreviews").RuleOrDie() + _, err := oc.AdminKubeClient().RbacV1().Roles(sa.Namespace).Create( + ctx, + &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: "pspssr"}, + Rules: []rbacv1.PolicyRule{rule}, + }, + metav1.CreateOptions{}, + ) + o.Expect(err).NotTo(o.HaveOccurred()) + + framework.Logf("Creating podsecuritypolicyselfsubjectreviews rolebinding") + _, err = oc.AdminKubeClient().RbacV1().RoleBindings(sa.Namespace).Create(ctx, &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: sa.Namespace, + GenerateName: "podadmin-", + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: sa.Name, + }, + }, + RoleRef: rbacv1.RoleRef{ + Kind: "Role", + Name: "pspssr", + }, + }, metav1.CreateOptions{}) + o.Expect(err).NotTo(o.HaveOccurred()) +} + +func createClientFromServiceAccount(oc *exutil.CLI, sa *corev1.ServiceAccount) (*kubernetes.Clientset, *securityv1client.SecurityV1Client) { + // create a new token request for the service account and use it to build a client for it + tokenRequest := &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + Audiences: []string{"https://kubernetes.default.svc"}, + }, + } + framework.Logf("Creating service account token") + bootstrapperToken, err := oc.AdminKubeClient().CoreV1().ServiceAccounts(sa.Namespace).CreateToken(context.TODO(), sa.Name, tokenRequest, metav1.CreateOptions{}) + o.Expect(err).NotTo(o.HaveOccurred()) + + saClientConfig := restclient.AnonymousClientConfig(oc.AdminConfig()) + saClientConfig.BearerToken = bootstrapperToken.Status.Token + + return kubernetes.NewForConfigOrDie(saClientConfig), securityv1client.NewForConfigOrDie(saClientConfig) +} diff --git a/test/extended/testdata/bindata.go b/test/extended/testdata/bindata.go index ebfc17131cea..6d00fe14907a 100644 --- a/test/extended/testdata/bindata.go +++ b/test/extended/testdata/bindata.go @@ -175,7 +175,6 @@ // test/extended/testdata/builds/webhook/github/testdata/pushevent.json // test/extended/testdata/builds/webhook/gitlab/testdata/pushevent-not-master-branch.json // test/extended/testdata/builds/webhook/gitlab/testdata/pushevent.json -// test/extended/testdata/cli/pod-with-two-containers.yaml // test/extended/testdata/cluster/master-vert.yaml // test/extended/testdata/cluster/quickstarts/cakephp-mysql.json // test/extended/testdata/cluster/quickstarts/dancer-mysql.json @@ -24142,57 +24141,6 @@ func testExtendedTestdataBuildsWebhookGitlabTestdataPusheventJson() (*asset, err return a, nil } -var _testExtendedTestdataCliPodWithTwoContainersYaml = []byte(`kind: Pod -apiVersion: v1 -metadata: - name: doublecontainers - labels: - name: hello-centos -spec: - containers: - - name: hello-centos - image: image-registry.openshift-image-registry.svc:5000/openshift/tools:latest - command: - - /bin/sleep - - infinity - resources: - limits: - memory: 256Mi - terminationMessagePath: "/dev/termination-log" - imagePullPolicy: IfNotPresent - securityContext: {} - - name: hello-centos-2 - image: image-registry.openshift-image-registry.svc:5000/openshift/tools:latest - command: - - /bin/sleep - - infinity - resources: - limits: - memory: 256Mi - terminationMessagePath: "/dev/termination-log1" - imagePullPolicy: IfNotPresent - securityContext: {} - restartPolicy: Always - dnsPolicy: ClusterFirst - serviceAccount: '' -status: {} -`) - -func testExtendedTestdataCliPodWithTwoContainersYamlBytes() ([]byte, error) { - return _testExtendedTestdataCliPodWithTwoContainersYaml, nil -} - -func testExtendedTestdataCliPodWithTwoContainersYaml() (*asset, error) { - bytes, err := testExtendedTestdataCliPodWithTwoContainersYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "test/extended/testdata/cli/pod-with-two-containers.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - var _testExtendedTestdataClusterMasterVertYaml = []byte(`provider: local ClusterLoader: cleanup: true @@ -52902,7 +52850,6 @@ var _bindata = map[string]func() (*asset, error){ "test/extended/testdata/builds/webhook/github/testdata/pushevent.json": testExtendedTestdataBuildsWebhookGithubTestdataPusheventJson, "test/extended/testdata/builds/webhook/gitlab/testdata/pushevent-not-master-branch.json": testExtendedTestdataBuildsWebhookGitlabTestdataPusheventNotMasterBranchJson, "test/extended/testdata/builds/webhook/gitlab/testdata/pushevent.json": testExtendedTestdataBuildsWebhookGitlabTestdataPusheventJson, - "test/extended/testdata/cli/pod-with-two-containers.yaml": testExtendedTestdataCliPodWithTwoContainersYaml, "test/extended/testdata/cluster/master-vert.yaml": testExtendedTestdataClusterMasterVertYaml, "test/extended/testdata/cluster/quickstarts/cakephp-mysql.json": testExtendedTestdataClusterQuickstartsCakephpMysqlJson, "test/extended/testdata/cluster/quickstarts/dancer-mysql.json": testExtendedTestdataClusterQuickstartsDancerMysqlJson, @@ -53527,9 +53474,6 @@ var _bintree = &bintree{nil, map[string]*bintree{ }}, }}, }}, - "cli": {nil, map[string]*bintree{ - "pod-with-two-containers.yaml": {testExtendedTestdataCliPodWithTwoContainersYaml, map[string]*bintree{}}, - }}, "cluster": {nil, map[string]*bintree{ "master-vert.yaml": {testExtendedTestdataClusterMasterVertYaml, map[string]*bintree{}}, "quickstarts": {nil, map[string]*bintree{ diff --git a/test/extended/testdata/cli/pod-with-two-containers.yaml b/test/extended/testdata/cli/pod-with-two-containers.yaml deleted file mode 100644 index e176a6625587..000000000000 --- a/test/extended/testdata/cli/pod-with-two-containers.yaml +++ /dev/null @@ -1,34 +0,0 @@ -kind: Pod -apiVersion: v1 -metadata: - name: doublecontainers - labels: - name: hello-centos -spec: - containers: - - name: hello-centos - image: image-registry.openshift-image-registry.svc:5000/openshift/tools:latest - command: - - /bin/sleep - - infinity - resources: - limits: - memory: 256Mi - terminationMessagePath: "/dev/termination-log" - imagePullPolicy: IfNotPresent - securityContext: {} - - name: hello-centos-2 - image: image-registry.openshift-image-registry.svc:5000/openshift/tools:latest - command: - - /bin/sleep - - infinity - resources: - limits: - memory: 256Mi - terminationMessagePath: "/dev/termination-log1" - imagePullPolicy: IfNotPresent - securityContext: {} - restartPolicy: Always - dnsPolicy: ClusterFirst - serviceAccount: '' -status: {} diff --git a/test/extended/util/annotate/generated/zz_generated.annotations.go b/test/extended/util/annotate/generated/zz_generated.annotations.go index f462a9e6f23e..8204cc896b91 100644 --- a/test/extended/util/annotate/generated/zz_generated.annotations.go +++ b/test/extended/util/annotate/generated/zz_generated.annotations.go @@ -615,7 +615,7 @@ var Annotations = map[string]string{ "[sig-arch] Managed cluster should ensure platform components have system-* priority class associated": " [Suite:openshift/conformance/parallel]", - "[sig-arch] Managed cluster should ensure pods use downstream images from our release image with proper ImagePullPolicy": " [Suite:openshift/conformance/parallel]", + "[sig-arch] Managed cluster should ensure pods use downstream images from our release image with proper ImagePullPolicy [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-arch] Managed cluster should have operators on the cluster version [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", @@ -813,10 +813,14 @@ var Annotations = map[string]string{ "[sig-auth][Feature:SecurityContextConstraints] TestAllowedSCCViaRBAC [apigroup:project.openshift.io][apigroup:user.openshift.io][apigroup:authorization.openshift.io][apigroup:security.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-auth][Feature:SecurityContextConstraints] TestAllowedSCCViaRBAC with service account [apigroup:security.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-auth][Feature:SecurityContextConstraints] TestPodDefaultCapabilities": " [Suite:openshift/conformance/parallel]", "[sig-auth][Feature:SecurityContextConstraints] TestPodUpdateSCCEnforcement [apigroup:user.openshift.io][apigroup:authorization.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-auth][Feature:SecurityContextConstraints] TestPodUpdateSCCEnforcement with service account": " [Suite:openshift/conformance/parallel]", + "[sig-auth][Feature:UserAPI] groups should work [apigroup:user.openshift.io][apigroup:project.openshift.io][apigroup:authorization.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-auth][Feature:UserAPI] users can manipulate groups [apigroup:user.openshift.io][apigroup:authorization.openshift.io][apigroup:project.openshift.io]": " [Suite:openshift/conformance/parallel]", @@ -1369,7 +1373,7 @@ var Annotations = map[string]string{ "[sig-cli] oc adm role-reapers [apigroup:authorization.openshift.io][apigroup:user.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc adm role-selectors": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc adm role-selectors [apigroup:template.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc adm serviceaccounts": " [Suite:openshift/conformance/parallel]", @@ -1385,11 +1389,23 @@ var Annotations = map[string]string{ "[sig-cli] oc api-resources can output expected information about api-resources": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc api-resources can output expected information about build.openshift.io api-resources [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc api-resources can output expected information about image.openshift.io api-resources [apigroup:image.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc api-resources can output expected information about operator.openshift.io api-resources [apigroup:operator.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc api-resources can output expected information about project.openshift.io api-resources [apigroup:project.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc api-resources can output expected information about route.openshift.io api-resources and api-version [apigroup:route.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc api-resources can output expected information about snapshot.storage.k8s.io api-resources [apigroup:snapshot.storage.k8s.io]": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc basics can create and interact with a list of resources": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc basics can create deploymentconfig and clusterquota": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc basics can create deploymentconfig and clusterquota [apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc basics can describe an OAuth access token": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc basics can describe an OAuth access token [apigroup:oauth.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc basics can get version information from API": " [Suite:openshift/conformance/parallel]", @@ -1397,9 +1413,9 @@ var Annotations = map[string]string{ "[sig-cli] oc basics can output expected --dry-run text": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc basics can patch resources": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc basics can patch resources [apigroup:user.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc basics can process templates": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc basics can process templates [apigroup:template.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc basics can show correct whoami result": " [Suite:openshift/conformance/parallel]", @@ -1417,7 +1433,7 @@ var Annotations = map[string]string{ "[sig-cli] oc can route traffic to services [apigroup:route.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc can run inside of a busybox container": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc can run inside of a busybox container [apigroup:image.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc completion returns expected help messages": " [Suite:openshift/conformance/parallel]", @@ -1437,11 +1453,45 @@ var Annotations = map[string]string{ "[sig-cli] oc explain networking types when using openshift-sdn should contain proper fields description for special networking types": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc explain should contain proper fields description for special types": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc explain should contain proper fields description for apps.openshift.io [apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for authorization.openshift.io [apigroup:authorization.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for config.openshift.io [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for console.openshift.io [apigroup:console.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for image.openshift.io [apigroup:image.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for oauth.openshift.io [apigroup:oauth.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for project.openshift.io [apigroup:project.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for route.openshift.io [apigroup:route.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for security.internal.openshift.io [apigroup:security.internal.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for security.openshift.io [apigroup:security.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for template.openshift.io [apigroup:template.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain proper fields description for user.openshift.io [apigroup:user.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc explain should contain proper spec+status for CRDs [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc explain should contain spec+status for builtinTypes": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc explain should contain spec+status for apps.openshift.io [apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain spec+status for build.openshift.io [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain spec+status for image.openshift.io [apigroup:image.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain spec+status for project.openshift.io [apigroup:project.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain spec+status for route.openshift.io [apigroup:route.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain spec+status for security.openshift.io [apigroup:security.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc explain should contain spec+status for template.openshift.io [apigroup:template.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc expose can ensure the expose command is functioning as expected [apigroup:route.openshift.io]": " [Suite:openshift/conformance/parallel]", @@ -1457,9 +1507,11 @@ var Annotations = map[string]string{ "[sig-cli] oc label pod": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc observe works as expected [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc observe works as expected with cluster operators [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-cli] oc observe works as expected": " [Suite:openshift/conformance/parallel]", - "[sig-cli] oc probe can ensure the probe command is functioning as expected on deploymentconfigs": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc probe can ensure the probe command is functioning as expected on deploymentconfigs [apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc probe can ensure the probe command is functioning as expected on pods": " [Suite:openshift/conformance/parallel]", @@ -1861,25 +1913,25 @@ var Annotations = map[string]string{ "[sig-instrumentation] MetricsGrabber should grab all metrics from a Scheduler.": " [Disabled:Broken] [Suite:k8s]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should have a AlertmanagerReceiversNotConfigured alert in firing state": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should have a AlertmanagerReceiversNotConfigured alert in firing state": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should have important platform topology metrics [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should have important platform topology metrics [apigroup:config.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should have non-Pod host cAdvisor metrics": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should have non-Pod host cAdvisor metrics": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should provide ingress metrics": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should provide ingress metrics": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should provide named network metrics [apigroup:project.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should provide named network metrics [apigroup:project.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should report telemetry [Late]": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should report telemetry [Late]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should start and expose a secured proxy and unsecured metrics [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster should start and expose a secured proxy and unsecured metrics [apigroup:config.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster shouldn't have failing rules evaluation": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster shouldn't have failing rules evaluation": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster shouldn't report any alerts in firing state apart from Watchdog and AlertmanagerReceiversNotConfigured [Early][apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster shouldn't report any alerts in firing state apart from Watchdog and AlertmanagerReceiversNotConfigured [Early][apigroup:config.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster when using openshift-sdn should be able to get the sdn ovs flows": " [Suite:openshift/conformance/parallel]", + "[sig-instrumentation] Prometheus [apigroup:image.openshift.io] when installed on the cluster when using openshift-sdn should be able to get the sdn ovs flows": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", "[sig-instrumentation] Stackdriver Monitoring should have accelerator metrics [Feature:StackdriverAcceleratorMonitoring]": " [Disabled:Unimplemented] [Suite:k8s]", @@ -1917,19 +1969,19 @@ var Annotations = map[string]string{ "[sig-network-edge][Conformance][Area:Networking][Feature:Router][apigroup:route.openshift.io][apigroup:config.openshift.io] The HAProxy router should pass the http2 tests [apigroup:image.openshift.io][apigroup:template.openshift.io]": " [Suite:openshift/conformance/parallel/minimal]", - "[sig-network-edge][Feature:Idling] Idling with a single service and DeploymentConfig should idle the service and DeploymentConfig properly [apigroup:apps.openshift.io]": " [Disabled:Broken]", + "[sig-network-edge][Feature:Idling] Idling with a single service and DeploymentConfig [apigroup:route.openshift.io] should idle the service and DeploymentConfig properly [apigroup:apps.openshift.io]": " [Disabled:Broken]", "[sig-network-edge][Feature:Idling] Idling with a single service and ReplicationController should idle the service and ReplicationController properly": " [Suite:openshift/conformance/parallel]", - "[sig-network-edge][Feature:Idling] Unidling should handle many TCP connections by possibly dropping those over a certain bound [Serial]": " [Skipped:Network/OVNKubernetes] [Suite:openshift/conformance/serial]", + "[sig-network-edge][Feature:Idling] Unidling [apigroup:apps.openshift.io][apigroup:route.openshift.io] should handle many TCP connections by possibly dropping those over a certain bound [Serial]": " [Skipped:Network/OVNKubernetes] [Suite:openshift/conformance/serial]", - "[sig-network-edge][Feature:Idling] Unidling should handle many UDP senders (by continuing to drop all packets on the floor) [Serial]": " [Suite:openshift/conformance/serial]", + "[sig-network-edge][Feature:Idling] Unidling [apigroup:apps.openshift.io][apigroup:route.openshift.io] should handle many UDP senders (by continuing to drop all packets on the floor) [Serial]": " [Suite:openshift/conformance/serial]", - "[sig-network-edge][Feature:Idling] Unidling should work with TCP (when fully idled)": " [Skipped:Network/OVNKubernetes] [Suite:openshift/conformance/parallel]", + "[sig-network-edge][Feature:Idling] Unidling [apigroup:apps.openshift.io][apigroup:route.openshift.io] should work with TCP (when fully idled)": " [Skipped:Network/OVNKubernetes] [Suite:openshift/conformance/parallel]", - "[sig-network-edge][Feature:Idling] Unidling should work with TCP (while idling)": " [Disabled:Broken] [Skipped:Network/OVNKubernetes]", + "[sig-network-edge][Feature:Idling] Unidling [apigroup:apps.openshift.io][apigroup:route.openshift.io] should work with TCP (while idling)": " [Disabled:Broken] [Skipped:Network/OVNKubernetes]", - "[sig-network-edge][Feature:Idling] Unidling should work with UDP": " [Suite:openshift/conformance/parallel]", + "[sig-network-edge][Feature:Idling] Unidling [apigroup:apps.openshift.io][apigroup:route.openshift.io] should work with UDP": " [Suite:openshift/conformance/parallel]", "[sig-network] CVE-2021-29923 IPv4 Service Type ClusterIP with leading zeros should work interpreted as decimal": " [Suite:openshift/conformance/parallel] [Suite:k8s]", @@ -2475,9 +2527,9 @@ var Annotations = map[string]string{ "[sig-network] services basic functionality should allow connections to another pod on the same node via a service IP": " [Suite:openshift/conformance/parallel]", - "[sig-network] services when running openshift ipv4 cluster ensures external ip policy is configured correctly on the cluster [Serial]": " [Suite:openshift/conformance/serial]", + "[sig-network] services when running openshift ipv4 cluster ensures external ip policy is configured correctly on the cluster [apigroup:config.openshift.io] [Serial]": " [Suite:openshift/conformance/serial]", - "[sig-network] services when running openshift ipv4 cluster on bare metal [apigroup:config.openshift.io] ensures external auto assign cidr is configured correctly on the cluster [Serial]": " [Suite:openshift/conformance/serial]", + "[sig-network] services when running openshift ipv4 cluster on bare metal [apigroup:config.openshift.io] ensures external auto assign cidr is configured correctly on the cluster [apigroup:config.openshift.io] [Serial]": " [Suite:openshift/conformance/serial]", "[sig-network] services when using a plugin in a mode that does not isolate namespaces by default should allow connections to pods in different namespaces on different nodes via service IPs": " [Suite:openshift/conformance/parallel]", @@ -2517,7 +2569,7 @@ var Annotations = map[string]string{ "[sig-network][Feature:EgressRouterCNI] when using openshift ovn-kubernetes should ensure ipv6 egressrouter cni resources are created [apigroup:operator.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:Multus] should use multus to create net1 device from network-attachment-definition": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:Multus] should use multus to create net1 device from network-attachment-definition [apigroup:k8s.cni.cncf.io]": " [Suite:openshift/conformance/parallel]", "[sig-network][Feature:Network Policy Audit logging] when using openshift ovn-kubernetes should ensure acl logs are created and correct [apigroup:project.openshift.io][apigroup:network.openshift.io]": " [Suite:openshift/conformance/parallel]", @@ -2559,23 +2611,23 @@ var Annotations = map[string]string{ "[sig-network][Feature:Router][apigroup:route.openshift.io][apigroup:template.openshift.io] The HAProxy router should serve the correct routes when scoped to a single namespace and label set": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:Whereabouts] should assign unique IP addresses to each pod in the event of a race condition case": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:Whereabouts] should assign unique IP addresses to each pod in the event of a race condition case [apigroup:k8s.cni.cncf.io]": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:Whereabouts] should use whereabouts net-attach-def to limit IP ranges for newly created pods": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:Whereabouts] should use whereabouts net-attach-def to limit IP ranges for newly created pods [apigroup:k8s.cni.cncf.io]": " [Suite:openshift/conformance/parallel]", "[sig-network][Feature:bond] should create a pod with bond interface": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:tuning] pod should not start for sysctls not on whitelist net.ipv4.conf.IFNAME.arp_filter": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:tuning] pod should not start for sysctls not on whitelist [apigroup:k8s.cni.cncf.io] net.ipv4.conf.IFNAME.arp_filter": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:tuning] pod should not start for sysctls not on whitelist net.ipv4.conf.all.send_redirects": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:tuning] pod should not start for sysctls not on whitelist [apigroup:k8s.cni.cncf.io] net.ipv4.conf.all.send_redirects": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:tuning] pod should start with all sysctl on whitelist": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:tuning] pod should start with all sysctl on whitelist [apigroup:k8s.cni.cncf.io]": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:tuning] pod sysctl should not affect existing pods": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:tuning] pod sysctl should not affect existing pods [apigroup:k8s.cni.cncf.io]": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:tuning] pod sysctl should not affect newly created pods": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:tuning] pod sysctl should not affect newly created pods [apigroup:k8s.cni.cncf.io]": " [Suite:openshift/conformance/parallel]", - "[sig-network][Feature:tuning] pod sysctls should not affect node": " [Suite:openshift/conformance/parallel]", + "[sig-network][Feature:tuning] pod sysctls should not affect node [apigroup:k8s.cni.cncf.io]": " [Suite:openshift/conformance/parallel]", "[sig-network][endpoints] admission [apigroup:config.openshift.io] blocks manual creation of EndpointSlices pointing to the cluster or service network": " [Suite:openshift/conformance/parallel]", diff --git a/test/extended/util/annotate/rules.go b/test/extended/util/annotate/rules.go index 1077f96490fe..8dda7c06d2b5 100644 --- a/test/extended/util/annotate/rules.go +++ b/test/extended/util/annotate/rules.go @@ -65,7 +65,7 @@ var ( `\[sig-network\] \[Feature:IPv6DualStack\] should have ipv4 and ipv6 node podCIDRs`, // https://bugzilla.redhat.com/show_bug.cgi?id=2004074 - `\[sig-network-edge\]\[Feature:Idling\] Unidling should work with TCP \(while idling\)`, + `\[sig-network-edge\]\[Feature:Idling\] Unidling \[apigroup:apps.openshift.io\]\[apigroup:route.openshift.io\] should work with TCP \(while idling\)`, // https://bugzilla.redhat.com/show_bug.cgi?id=2070929 `\[sig-network\]\[Feature:EgressIP\]\[apigroup:config.openshift.io\] \[internal-targets\]`, @@ -244,16 +244,16 @@ var ( `\[sig-imageregistry\]\[Feature:ImageTriggers\] Annotation trigger reconciles after the image is overwritten`, `\[sig-imageregistry\]\[Feature:Image\] oc tag should change image reference for internal images`, `\[sig-imageregistry\]\[Feature:Image\] oc tag should work when only imagestreams api is available`, - `\[sig-instrumentation\] Prometheus when installed on the cluster should have a AlertmanagerReceiversNotConfigured alert in firing state`, - `\[sig-instrumentation\] Prometheus when installed on the cluster should have important platform topology metrics`, - `\[sig-instrumentation\] Prometheus when installed on the cluster should have non-Pod host cAdvisor metrics`, - `\[sig-instrumentation\] Prometheus when installed on the cluster should provide ingress metrics`, - `\[sig-instrumentation\] Prometheus when installed on the cluster should provide named network metrics`, - `\[sig-instrumentation\] Prometheus when installed on the cluster should report telemetry \[Late\]`, - `\[sig-instrumentation\] Prometheus when installed on the cluster should start and expose a secured proxy and unsecured metrics`, - `\[sig-instrumentation\] Prometheus when installed on the cluster shouldn't have failing rules evaluation`, - `\[sig-instrumentation\] Prometheus when installed on the cluster shouldn't report any alerts in firing state apart from Watchdog and AlertmanagerReceiversNotConfigured \[Early\]`, - `\[sig-instrumentation\] Prometheus when installed on the cluster when using openshift-sdn should be able to get the sdn ovs flows`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster should have a AlertmanagerReceiversNotConfigured alert in firing state`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster should have important platform topology metrics`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster should have non-Pod host cAdvisor metrics`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster should provide ingress metrics`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster should provide named network metrics`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster should report telemetry \[Late\]`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster should start and expose a secured proxy and unsecured metrics`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster shouldn't have failing rules evaluation`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster shouldn't report any alerts in firing state apart from Watchdog and AlertmanagerReceiversNotConfigured \[Early\]`, + `\[sig-instrumentation\] Prometheus \[apigroup:image.openshift.io\] when installed on the cluster when using openshift-sdn should be able to get the sdn ovs flows`, `\[sig-instrumentation\]\[Late\] OpenShift alerting rules \[apigroup:image.openshift.io\] should have a valid severity label`, `\[sig-instrumentation\]\[Late\] OpenShift alerting rules \[apigroup:image.openshift.io\] should have description and summary annotations`, `\[sig-instrumentation\]\[Late\] OpenShift alerting rules \[apigroup:image.openshift.io\] should have a runbook_url annotation if the alert is critical`, @@ -309,8 +309,8 @@ var ( `NetworkPolicy.*named port`, // https://bugzilla.redhat.com/show_bug.cgi?id=1989169: unidling tests are flaky under ovn-kubernetes - `Unidling should work with TCP`, - `Unidling should handle many TCP connections`, + `Unidling \[apigroup:apps.openshift.io\]\[apigroup:route.openshift.io\] should work with TCP`, + `Unidling \[apigroup:apps.openshift.io\]\[apigroup:route.openshift.io\] should handle many TCP connections`, }, "[Skipped:ibmroks]": { // skip Gluster tests (not supported on ROKS worker nodes) diff --git a/test/extended/util/client.go b/test/extended/util/client.go index d20194531be5..e96d2176f37a 100644 --- a/test/extended/util/client.go +++ b/test/extended/util/client.go @@ -1025,29 +1025,29 @@ func turnOffRateLimiting(config *rest.Config) *rest.Config { func (c *CLI) WaitForAccessAllowed(review *kubeauthorizationv1.SelfSubjectAccessReview, user string) error { if user == "system:anonymous" { - return waitForAccess(kubernetes.NewForConfigOrDie(rest.AnonymousClientConfig(c.AdminConfig())), true, review) + return WaitForAccess(kubernetes.NewForConfigOrDie(rest.AnonymousClientConfig(c.AdminConfig())), true, review) } kubeClient, err := kubernetes.NewForConfig(c.GetClientConfigForUser(user)) if err != nil { FatalErr(err) } - return waitForAccess(kubeClient, true, review) + return WaitForAccess(kubeClient, true, review) } func (c *CLI) WaitForAccessDenied(review *kubeauthorizationv1.SelfSubjectAccessReview, user string) error { if user == "system:anonymous" { - return waitForAccess(kubernetes.NewForConfigOrDie(rest.AnonymousClientConfig(c.AdminConfig())), false, review) + return WaitForAccess(kubernetes.NewForConfigOrDie(rest.AnonymousClientConfig(c.AdminConfig())), false, review) } kubeClient, err := kubernetes.NewForConfig(c.GetClientConfigForUser(user)) if err != nil { FatalErr(err) } - return waitForAccess(kubeClient, false, review) + return WaitForAccess(kubeClient, false, review) } -func waitForAccess(c kubernetes.Interface, allowed bool, review *kubeauthorizationv1.SelfSubjectAccessReview) error { +func WaitForAccess(c kubernetes.Interface, allowed bool, review *kubeauthorizationv1.SelfSubjectAccessReview) error { return wait.Poll(time.Second, time.Minute, func() (bool, error) { response, err := c.AuthorizationV1().SelfSubjectAccessReviews().Create(context.Background(), review, metav1.CreateOptions{}) if err != nil { diff --git a/test/extended/util/framework.go b/test/extended/util/framework.go index 755f2165a330..812917473f46 100644 --- a/test/extended/util/framework.go +++ b/test/extended/util/framework.go @@ -1942,6 +1942,17 @@ func GetRouterPodTemplate(oc *CLI) (*corev1.PodTemplateSpec, string, error) { } func FindRouterImage(oc *CLI) (string, error) { + exists, err := DoesApiResourceExist(oc.AdminConfig(), "clusteroperators") + if err != nil { + return "", err + } + if !exists { + deployment, err := oc.AdminKubeClient().AppsV1().Deployments("openshift-ingress").Get(context.Background(), "router-default", metav1.GetOptions{}) + if err != nil { + return "", err + } + return deployment.Spec.Template.Spec.Containers[0].Image, nil + } configclient := oc.AdminConfigClient().ConfigV1() o, err := configclient.ClusterOperators().Get(context.Background(), "ingress", metav1.GetOptions{}) if err != nil {