diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a162a6ff8b..0333a2ad05c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ #### _**Note**_: Breaking changes * Fix #4574: fromServer has been deprecated - it no longer needs to be called. All get() operations will fetch the resource(s) from the api server. If you need the context item that was passed in from a resource, load, or resourceList methods, use the item or items method. * Fix #4633: client.run().withRunConfig was deprecated. Use withNewRunConfig instead. +* Fix #4014: Support for Openshift 3.9 and 3.10 have been dropped because the RoleBinding logic no longer supports setting both the subjects and groups and the usernames and groupnames. You may still use a newer client against legacy versions if you take responsibility for setting the usernames and groupnames fields on your own. ### 6.3.1 (2022-12-15) diff --git a/kubernetes-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenshiftRoleBindingTest.java b/kubernetes-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenshiftRoleBindingTest.java index e392ffb05d4..6bdceed5b6f 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenshiftRoleBindingTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenshiftRoleBindingTest.java @@ -16,6 +16,8 @@ package io.fabric8.openshift.client.server.mock; import com.fasterxml.jackson.databind.ObjectMapper; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.openshift.api.model.RoleBinding; import io.fabric8.openshift.api.model.RoleBindingBuilder; import io.fabric8.openshift.client.OpenShiftClient; @@ -23,17 +25,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -@EnableOpenShiftMockClient +@EnableKubernetesMockClient class OpenshiftRoleBindingTest { - OpenShiftMockServer server; + KubernetesMockServer server; OpenShiftClient client; private RoleBinding expectedRoleBinding = new RoleBindingBuilder() .withNewMetadata() + .withName("testrb") .endMetadata() - .addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct") - .addToGroupNames("testgroup") .addNewSubject() .withKind("User") .withName("testuser1") @@ -44,7 +45,6 @@ class OpenshiftRoleBindingTest { .endSubject() .addNewSubject() .withKind("ServiceAccount") - .withNamespace("test") .withName("svcacct") .endSubject() .addNewSubject() @@ -62,9 +62,10 @@ void testCreateWithOnlySubjects() throws Exception { .once(); RoleBinding response = client.roleBindings() - .create( + .resource( new RoleBindingBuilder() .withNewMetadata() + .withName("testrb") .endMetadata() .addNewSubject() .withKind("User") @@ -82,60 +83,14 @@ void testCreateWithOnlySubjects() throws Exception { .withKind("Group") .withName("testgroup") .endSubject() - .build()); + .build()) + .create(); assertEquals(expectedRoleBinding, response); assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(server.getLastRequest().getBody().readByteArray())); } - @Test - void testCreateWithUserNamesAndGroupsAndNoSubjects() throws Exception { - server.expect() - .post() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings") - .andReturn(201, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .create( - new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct") - .addToGroupNames("testgroup") - .build()); - assertEquals(expectedRoleBinding, response); - assertEquals(expectedRoleBinding, - new ObjectMapper().readerFor(RoleBinding.class).readValue(server.getLastRequest().getBody().inputStream())); - } - - @Test - void testCreateWithUserNamesAndGroupsAndOverwriteSubjects() throws Exception { - server.expect() - .post() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings") - .andReturn(201, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .create( - new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct") - .addToGroupNames("testgroup") - .addNewSubject() - .withKind("User") - .withName("unexpected") - .endSubject() - .build()); - assertEquals(expectedRoleBinding, response); - - assertEquals(expectedRoleBinding, - new ObjectMapper().readerFor(RoleBinding.class).readValue(server.getLastRequest().getBody().inputStream())); - } - @Test void testReplaceWithOnlySubjects() throws Exception { server.expect() @@ -150,10 +105,10 @@ void testReplaceWithOnlySubjects() throws Exception { .once(); RoleBinding response = client.roleBindings() - .withName("testrb") - .replace( + .resource( new RoleBindingBuilder() .withNewMetadata() + .withName("testrb") .endMetadata() .addNewSubject() .withKind("User") @@ -171,210 +126,12 @@ void testReplaceWithOnlySubjects() throws Exception { .withKind("Group") .withName("testgroup") .endSubject() - .build()); + .build()) + .replace(); assertEquals(expectedRoleBinding, response); assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(server.getLastRequest().getBody().inputStream())); } - @Test - void testReplaceWithUserNamesAndGroupsAndNoSubjects() throws Exception { - server.expect() - .get() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, expectedRoleBinding) - .once(); - server.expect() - .put() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .withName("testrb") - .replace( - new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct") - .addToGroupNames("testgroup") - .build()); - assertEquals(expectedRoleBinding, response); - - assertEquals(expectedRoleBinding, - new ObjectMapper().readerFor(RoleBinding.class).readValue(server.getLastRequest().getBody().inputStream())); - } - - @Test - void testReplaceWithUserNamesAndGroupsAndOverwriteSubjects() throws Exception { - server.expect() - .get() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, expectedRoleBinding) - .once(); - server.expect() - .put() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .withName("testrb") - .replace( - new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct") - .addToGroupNames("testgroup") - .addNewSubject() - .withKind("User") - .withName("unexpected") - .endSubject() - .build()); - assertEquals(expectedRoleBinding, response); - - assertEquals(expectedRoleBinding, - new ObjectMapper().readerFor(RoleBinding.class).readValue(server.getLastRequest().getBody().inputStream())); - } - - @Test - void testPatchWithOnlySubjects() throws Exception { - server.expect() - .get() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, new RoleBindingBuilder().addToUserNames("unexpected").build()) - .once(); - server.expect() - .patch() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .withName("testrb") - .patch( - new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addNewSubject() - .withKind("User") - .withName("testuser1") - .endSubject() - .addNewSubject() - .withKind("User") - .withName("testuser2") - .endSubject() - .addNewSubject() - .withKind("ServiceAccount") - .withName("svcacct") - .endSubject() - .addNewSubject() - .withKind("Group") - .withName("testgroup") - .endSubject() - .build()); - assertEquals(expectedRoleBinding, response); - - assertEquals( - "[{\"op\":\"replace\",\"path\":\"/userNames/0\",\"value\":\"testuser1\"},{\"op\":\"add\",\"path\":\"/userNames/1\",\"value\":\"testuser2\"},{\"op\":\"add\",\"path\":\"/userNames/2\",\"value\":\"system:serviceaccount:test:svcacct\"},{\"op\":\"add\",\"path\":\"/metadata\",\"value\":{}},{\"op\":\"add\",\"path\":\"/groupNames\",\"value\":[\"testgroup\"]},{\"op\":\"add\",\"path\":\"/subjects\",\"value\":[{\"kind\":\"User\",\"name\":\"testuser1\"},{\"kind\":\"User\",\"name\":\"testuser2\"},{\"kind\":\"ServiceAccount\",\"name\":\"svcacct\",\"namespace\":\"test\"},{\"kind\":\"Group\",\"name\":\"testgroup\"}]}]", - server.getLastRequest().getBody().readUtf8()); - } - - @Test - void testPatchWithUserNamesAndGroupsAndNoSubjects() throws Exception { - server.expect() - .get() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, new RoleBindingBuilder().addToUserNames("unexpected").build()) - .once(); - server.expect() - .patch() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .withName("testrb") - .patch( - new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct") - .addToGroupNames("testgroup") - .build()); - assertEquals(expectedRoleBinding, response); - - assertEquals( - "[{\"op\":\"replace\",\"path\":\"/userNames/0\",\"value\":\"testuser1\"},{\"op\":\"add\",\"path\":\"/userNames/1\",\"value\":\"testuser2\"},{\"op\":\"add\",\"path\":\"/userNames/2\",\"value\":\"system:serviceaccount:test:svcacct\"},{\"op\":\"add\",\"path\":\"/metadata\",\"value\":{}},{\"op\":\"add\",\"path\":\"/groupNames\",\"value\":[\"testgroup\"]},{\"op\":\"add\",\"path\":\"/subjects\",\"value\":[{\"kind\":\"User\",\"name\":\"testuser1\"},{\"kind\":\"User\",\"name\":\"testuser2\"},{\"kind\":\"ServiceAccount\",\"name\":\"svcacct\",\"namespace\":\"test\"},{\"kind\":\"Group\",\"name\":\"testgroup\"}]}]", - server.getLastRequest().getBody().readUtf8()); - } - - @Test - void testPatchWithUserNamesAndGroupsAndOverwriteSubjects() throws Exception { - server.expect() - .get() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, new RoleBindingBuilder().addToUserNames("unexpected").build()) - .once(); - server.expect() - .patch() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings/testrb") - .andReturn(200, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .withName("testrb") - .patch( - new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct") - .addToGroupNames("testgroup") - .addNewSubject() - .withKind("User") - .withName("unexpected") - .endSubject() - .build()); - assertEquals(expectedRoleBinding, response); - - assertEquals( - "[{\"op\":\"replace\",\"path\":\"/userNames/0\",\"value\":\"testuser1\"},{\"op\":\"add\",\"path\":\"/userNames/1\",\"value\":\"testuser2\"},{\"op\":\"add\",\"path\":\"/userNames/2\",\"value\":\"system:serviceaccount:test:svcacct\"},{\"op\":\"add\",\"path\":\"/metadata\",\"value\":{}},{\"op\":\"add\",\"path\":\"/groupNames\",\"value\":[\"testgroup\"]},{\"op\":\"add\",\"path\":\"/subjects\",\"value\":[{\"kind\":\"User\",\"name\":\"testuser1\"},{\"kind\":\"User\",\"name\":\"testuser2\"},{\"kind\":\"ServiceAccount\",\"name\":\"svcacct\",\"namespace\":\"test\"},{\"kind\":\"Group\",\"name\":\"testgroup\"}]}]", - server.getLastRequest().getBody().readUtf8()); - } - - @Test - void testCreateInline() throws Exception { - server.expect() - .post() - .withPath("/apis/authorization.openshift.io/v1/namespaces/test/rolebindings") - .andReturn(201, expectedRoleBinding) - .once(); - - RoleBinding response = client.roleBindings() - .create(new RoleBindingBuilder() - .withNewMetadata() - .endMetadata() - .addNewSubject() - .withKind("User") - .withName("testuser1") - .endSubject() - .addNewSubject() - .withKind("User") - .withName("testuser2") - .endSubject() - .addNewSubject() - .withKind("ServiceAccount") - .withName("svcacct") - .endSubject() - .addNewSubject() - .withKind("Group") - .withName("testgroup") - .endSubject() - .build()); - assertEquals(expectedRoleBinding, response); - assertEquals(expectedRoleBinding, - new ObjectMapper().readerFor(RoleBinding.class).readValue(server.getLastRequest().getBody().inputStream())); - } - } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/authorization/RoleBindingOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/authorization/RoleBindingOperationsImpl.java deleted file mode 100644 index ade8da83beb..00000000000 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/authorization/RoleBindingOperationsImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright (C) 2015 Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.fabric8.openshift.client.dsl.internal.authorization; - -import io.fabric8.kubernetes.api.builder.TypedVisitor; -import io.fabric8.kubernetes.api.model.ObjectReference; -import io.fabric8.kubernetes.api.model.ObjectReferenceBuilder; -import io.fabric8.kubernetes.client.Client; -import io.fabric8.kubernetes.client.dsl.Resource; -import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; -import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperationsImpl; -import io.fabric8.kubernetes.client.dsl.internal.OperationContext; -import io.fabric8.openshift.api.model.RoleBinding; -import io.fabric8.openshift.api.model.RoleBindingBuilder; -import io.fabric8.openshift.api.model.RoleBindingList; - -import java.io.IOException; -import java.util.List; -import java.util.function.Supplier; - -import static io.fabric8.openshift.client.OpenShiftAPIGroups.AUTHORIZATION; - -public class RoleBindingOperationsImpl extends HasMetadataOperation> { - - public static final String SERVICE_ACCOUNT = "ServiceAccount"; - public static final String USER = "User"; - public static final String GROUP = "Group"; - - public RoleBindingOperationsImpl(Client client) { - this(HasMetadataOperationsImpl.defaultContext(client)); - } - - public RoleBindingOperationsImpl(OperationContext context) { - super(context.withApiGroupName(AUTHORIZATION) - .withPlural("rolebindings"), RoleBinding.class, RoleBindingList.class); - } - - @Override - public RoleBindingOperationsImpl newInstance(OperationContext context) { - return new RoleBindingOperationsImpl(context); - } - - @Override - protected RoleBinding handleCreate(RoleBinding resource) throws InterruptedException, IOException { - return super.handleCreate(enrichRoleBinding(resource)); - } - - @Override - protected RoleBinding modifyItemForReplaceOrPatch(Supplier current, RoleBinding binding) { - return enrichRoleBinding(binding); - } - - private RoleBinding enrichRoleBinding(RoleBinding binding) { - RoleBindingBuilder builder = new RoleBindingBuilder(binding); - - if ((binding.getUserNames() != null && !binding.getUserNames().isEmpty()) || - (binding.getGroupNames() != null && !binding.getGroupNames().isEmpty())) { - enrichFromUsersAndGroups(builder, binding.getUserNames(), binding.getGroupNames()); - } else { - enrichFromSubjects(builder, binding.getSubjects()); - enrichSubjectsNamespace(builder); - } - - return builder.build(); - } - - private void enrichSubjectsNamespace(RoleBindingBuilder builder) { - builder.accept(new TypedVisitor() { - @Override - public void visit(ObjectReferenceBuilder o) { - if (o.getKind() != null && o.getKind().equals(SERVICE_ACCOUNT) - && (o.getNamespace() == null || o.getNamespace().isEmpty())) { - o.withNamespace(getNamespace()); - } - } - }); - } - - private void enrichFromUsersAndGroups(RoleBindingBuilder builder, List userNames, List groupNames) { - builder.withSubjects(); - - if (userNames != null) { - for (String userName : userNames) { - if (userName.startsWith("system:serviceaccount:")) { - String[] splitUserName = userName.split(":"); - if (splitUserName.length == 4) { - builder.addNewSubject().withKind(SERVICE_ACCOUNT).withNamespace(splitUserName[2]).withName(splitUserName[3]) - .endSubject(); - continue; - } - } - - builder.addNewSubject().withKind(USER).withName(userName).endSubject(); - } - } - - if (groupNames != null) { - for (String groupName : groupNames) { - builder.addNewSubject().withKind(GROUP).withName(groupName).endSubject(); - } - } - } - - private void enrichFromSubjects(RoleBindingBuilder builder, List subjects) { - for (ObjectReference ref : subjects) { - switch (ref.getKind()) { - case USER: - builder.addToUserNames(ref.getName()); - break; - case SERVICE_ACCOUNT: - String namespace = ref.getNamespace(); - if (namespace == null || namespace.isEmpty()) { - namespace = getNamespace(); - } - builder.addToUserNames("system:serviceaccount:" + namespace + ":" + ref.getName()); - break; - case GROUP: - builder.addToGroupNames(ref.getName()); - break; - } - } - } -} diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java index 4997076f079..630854cdc19 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java @@ -166,7 +166,6 @@ import io.fabric8.openshift.client.dsl.ProjectRequestOperation; import io.fabric8.openshift.client.dsl.TemplateResource; import io.fabric8.openshift.client.dsl.internal.apps.DeploymentConfigOperationsImpl; -import io.fabric8.openshift.client.dsl.internal.authorization.RoleBindingOperationsImpl; import io.fabric8.openshift.client.dsl.internal.build.BuildConfigOperationsImpl; import io.fabric8.openshift.client.dsl.internal.build.BuildOperationsImpl; import io.fabric8.openshift.client.dsl.internal.core.TemplateOperationsImpl; @@ -480,7 +479,7 @@ public MixedOperation> roles() { @Override public MixedOperation> roleBindings() { - return new RoleBindingOperationsImpl(this); + return resources(RoleBinding.class, RoleBindingList.class); } @Override diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftExtensionAdapter.java b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftExtensionAdapter.java index 9a181acd7ec..54c22fb2362 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftExtensionAdapter.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftExtensionAdapter.java @@ -23,7 +23,6 @@ import io.fabric8.openshift.api.model.Build; import io.fabric8.openshift.api.model.BuildConfig; import io.fabric8.openshift.api.model.DeploymentConfig; -import io.fabric8.openshift.api.model.RoleBinding; import io.fabric8.openshift.api.model.Template; import io.fabric8.openshift.client.OpenShiftClient; import io.fabric8.openshift.client.dsl.MachineConfigurationAPIGroupDSL; @@ -42,7 +41,6 @@ import io.fabric8.openshift.client.dsl.V1ClusterAutoscalingAPIGroupDSL; import io.fabric8.openshift.client.dsl.V1beta1ClusterAutoscalingAPIGroupDSL; import io.fabric8.openshift.client.dsl.internal.apps.DeploymentConfigOperationsImpl; -import io.fabric8.openshift.client.dsl.internal.authorization.RoleBindingOperationsImpl; import io.fabric8.openshift.client.dsl.internal.build.BuildConfigOperationsImpl; import io.fabric8.openshift.client.dsl.internal.build.BuildOperationsImpl; import io.fabric8.openshift.client.dsl.internal.core.TemplateOperationsImpl; @@ -68,7 +66,6 @@ public void registerHandlers(Handlers handlers) { handlers.register(BuildConfig.class, BuildConfigOperationsImpl::new); handlers.register(Build.class, BuildOperationsImpl::new); handlers.register(DeploymentConfig.class, DeploymentConfigOperationsImpl::new); - handlers.register(RoleBinding.class, RoleBindingOperationsImpl::new); handlers.register(Template.class, TemplateOperationsImpl::new); }