Skip to content

Commit

Permalink
Enrich role bindings as required
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmidyson committed Oct 7, 2016
1 parent ca81c22 commit 0379c9b
Show file tree
Hide file tree
Showing 3 changed files with 351 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@
*/
package io.fabric8.openshift.client.dsl.internal;

import okhttp3.OkHttpClient;
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.KubernetesClientException;
import io.fabric8.kubernetes.client.dsl.ClientResource;
import io.fabric8.openshift.api.model.DoneableRoleBinding;
import io.fabric8.openshift.api.model.RoleBinding;
import io.fabric8.openshift.api.model.RoleBindingBuilder;
import io.fabric8.openshift.api.model.RoleBindingList;
import io.fabric8.openshift.client.OpenShiftConfig;
import okhttp3.OkHttpClient;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

Expand All @@ -33,4 +39,94 @@ public RoleBindingOperationsImpl(OkHttpClient client, OpenShiftConfig config, St
public RoleBindingOperationsImpl(OkHttpClient client, OpenShiftConfig config, String apiVersion, String namespace, String name, Boolean cascading, RoleBinding item, String resourceVersion, Boolean reloadingFromServer, long gracePeriodSeconds, Map<String, String> labels, Map<String, String> labelsNot, Map<String, String[]> labelsIn, Map<String, String[]> labelsNotIn, Map<String, String> fields) {
super(client, config, null, apiVersion, "rolebindings", namespace, name, cascading, item, resourceVersion, reloadingFromServer, gracePeriodSeconds, labels, labelsNot, labelsIn, labelsNotIn, fields);
}

@Override
public RoleBinding replace(RoleBinding item) {
RoleBinding enriched = enrichRoleBinding(item);
return super.replace(enriched);
}

@Override
public RoleBinding patch(RoleBinding item) {
RoleBinding enriched = enrichRoleBinding(item);
return super.patch(enriched);
}

@Override
public RoleBinding create(RoleBinding... resources) throws KubernetesClientException {
RoleBinding[] enriched = new RoleBinding[resources.length];
for (int i = 0; i < resources.length; i++) {
enriched[i] = enrichRoleBinding(resources[i]);
}
return super.create(enriched);
}

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<ObjectReferenceBuilder>() {
@Override
public void visit(ObjectReferenceBuilder o) {
if (o.getKind().equals("ServiceAccount") && (o.getNamespace() == null || o.getNamespace().isEmpty())) {
o.withNamespace(getNamespace());
}
}
});
}

private void enrichFromUsersAndGroups(RoleBindingBuilder builder, List<String> userNames, List<String> 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("ServiceAccount").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<ObjectReference> subjects) {
for (ObjectReference ref : subjects) {
switch (ref.getKind()) {
case "User":
builder.addToUserNames(ref.getName());
break;
case "ServiceAccount":
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;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.fabric8.mockwebserver.dsl.MockServerExpectation;
import io.fabric8.openshift.client.NamespacedOpenShiftClient;
import io.fabric8.openshift.server.mock.OpenShiftMockServer;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.rules.ExternalResource;

public class OpenShiftServer extends ExternalResource {
Expand Down Expand Up @@ -56,4 +57,8 @@ public <T> void expectAndReturnAsJson(String path, int code, T body) {
public void expectAndReturnAsString(String path, int code, String body) {
expect().withPath(path).andReturn(code, body).always();
}

public MockWebServer getMockServer() {
return mock.getServer();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
/**
* 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.mock;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.fabric8.openshift.api.model.RoleBinding;
import io.fabric8.openshift.api.model.RoleBindingBuilder;
import io.fabric8.openshift.client.NamespacedOpenShiftClient;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.Rule;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class RoleBindingTest {
@Rule
public OpenShiftServer server = new OpenShiftServer();

private RoleBinding expectedRoleBinding = new RoleBindingBuilder()
.withNewMetadata().endMetadata()
.addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct")
.addToGroupNames("testgroup")
.addNewSubject().withKind("User").withName("testuser1").endSubject()
.addNewSubject().withKind("User").withName("testuser2").endSubject()
.addNewSubject().withKind("ServiceAccount").withNamespace("test").withName("svcacct").endSubject()
.addNewSubject().withKind("Group").withName("testgroup").endSubject()
.build();

@Test
public void testCreateWithOnlySubjects() throws Exception {
server.expect().post().withPath("/oapi/v1/namespaces/test/rolebindings").andReturn(201, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

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);

RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(request.getBody().inputStream()));
}

@Test
public void testCreateWithUserNamesAndGroupsAndNoSubjects() throws Exception {
server.expect().post().withPath("/oapi/v1/namespaces/test/rolebindings").andReturn(201, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

RoleBinding response = client.roleBindings().create(
new RoleBindingBuilder()
.withNewMetadata().endMetadata()
.addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct")
.addToGroupNames("testgroup")
.build()
);
assertEquals(expectedRoleBinding, response);

RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(request.getBody().inputStream()));
}

@Test
public void testCreateWithUserNamesAndGroupsAndOverwriteSubjects() throws Exception {
server.expect().post().withPath("/oapi/v1/namespaces/test/rolebindings").andReturn(201, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

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);

RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(request.getBody().inputStream()));
}

@Test
public void testReplaceWithOnlySubjects() throws Exception {
server.expect().get().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();
server.expect().put().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

RoleBinding response = client.roleBindings().withName("testrb").replace(
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);

// Initial GET
server.getMockServer().takeRequest();
RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(request.getBody().inputStream()));
}

@Test
public void testReplaceWithUserNamesAndGroupsAndNoSubjects() throws Exception {
server.expect().get().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();
server.expect().put().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

RoleBinding response = client.roleBindings().withName("testrb").replace(
new RoleBindingBuilder()
.withNewMetadata().endMetadata()
.addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct")
.addToGroupNames("testgroup")
.build()
);
assertEquals(expectedRoleBinding, response);

// Initial GET
server.getMockServer().takeRequest();
RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(request.getBody().inputStream()));
}

@Test
public void testReplaceWithUserNamesAndGroupsAndOverwriteSubjects() throws Exception {
server.expect().get().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();
server.expect().put().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

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);

// Initial GET
server.getMockServer().takeRequest();
RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(expectedRoleBinding, new ObjectMapper().readerFor(RoleBinding.class).readValue(request.getBody().inputStream()));
}

@Test
public void testPatchWithOnlySubjects() throws Exception {
server.expect().get().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, new RoleBindingBuilder().addToUserNames("unexpected").build()).once();
server.expect().patch().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

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);

// Initial GET
server.getMockServer().takeRequest();
RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(
"[{\"op\":\"add\",\"path\":\"/groupNames/0\",\"value\":\"testgroup\"},{\"op\":\"add\",\"path\":\"/subjects/0\",\"value\":{\"kind\":\"User\",\"name\":\"testuser1\"}},{\"op\":\"add\",\"path\":\"/subjects/1\",\"value\":{\"kind\":\"User\",\"name\":\"testuser2\"}},{\"op\":\"add\",\"path\":\"/subjects/2\",\"value\":{\"kind\":\"ServiceAccount\",\"name\":\"svcacct\",\"namespace\":\"test\"}},{\"op\":\"add\",\"path\":\"/subjects/3\",\"value\":{\"kind\":\"Group\",\"name\":\"testgroup\"}},{\"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\":{\"annotations\":{},\"finalizers\":[],\"labels\":{},\"ownerReferences\":[]}}]",
request.getBody().readUtf8()
);
}

@Test
public void testPatchWithUserNamesAndGroupsAndNoSubjects() throws Exception {
server.expect().get().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, new RoleBindingBuilder().addToUserNames("unexpected").build()).once();
server.expect().patch().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

RoleBinding response = client.roleBindings().withName("testrb").patch(
new RoleBindingBuilder()
.withNewMetadata().endMetadata()
.addToUserNames("testuser1", "testuser2", "system:serviceaccount:test:svcacct")
.addToGroupNames("testgroup")
.build()
);
assertEquals(expectedRoleBinding, response);

// Initial GET
server.getMockServer().takeRequest();
RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(
"[{\"op\":\"add\",\"path\":\"/groupNames/0\",\"value\":\"testgroup\"},{\"op\":\"add\",\"path\":\"/subjects/0\",\"value\":{\"kind\":\"User\",\"name\":\"testuser1\"}},{\"op\":\"add\",\"path\":\"/subjects/1\",\"value\":{\"kind\":\"User\",\"name\":\"testuser2\"}},{\"op\":\"add\",\"path\":\"/subjects/2\",\"value\":{\"kind\":\"ServiceAccount\",\"name\":\"svcacct\",\"namespace\":\"test\"}},{\"op\":\"add\",\"path\":\"/subjects/3\",\"value\":{\"kind\":\"Group\",\"name\":\"testgroup\"}},{\"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\":{\"annotations\":{},\"finalizers\":[],\"labels\":{},\"ownerReferences\":[]}}]",
request.getBody().readUtf8()
);
}

@Test
public void testPatchWithUserNamesAndGroupsAndOverwriteSubjects() throws Exception {
server.expect().get().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, new RoleBindingBuilder().addToUserNames("unexpected").build()).once();
server.expect().patch().withPath("/oapi/v1/namespaces/test/rolebindings/testrb").andReturn(200, expectedRoleBinding).once();

NamespacedOpenShiftClient client = server.getOpenshiftClient();

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);

// Initial GET
server.getMockServer().takeRequest();
RecordedRequest request = server.getMockServer().takeRequest();
assertEquals(
"[{\"op\":\"add\",\"path\":\"/groupNames/0\",\"value\":\"testgroup\"},{\"op\":\"add\",\"path\":\"/subjects/0\",\"value\":{\"kind\":\"User\",\"name\":\"testuser1\"}},{\"op\":\"add\",\"path\":\"/subjects/1\",\"value\":{\"kind\":\"User\",\"name\":\"testuser2\"}},{\"op\":\"add\",\"path\":\"/subjects/2\",\"value\":{\"kind\":\"ServiceAccount\",\"name\":\"svcacct\",\"namespace\":\"test\"}},{\"op\":\"add\",\"path\":\"/subjects/3\",\"value\":{\"kind\":\"Group\",\"name\":\"testgroup\"}},{\"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\":{\"annotations\":{},\"finalizers\":[],\"labels\":{},\"ownerReferences\":[]}}]",
request.getBody().readUtf8()
);
}

}

0 comments on commit 0379c9b

Please sign in to comment.