Skip to content

Commit

Permalink
Fix fabric8io#2311: Add Support for creating bootstrap project template
Browse files Browse the repository at this point in the history
Just like `oc adm create-bootstrap-project-template` generates a template yaml for
project request resources to be created; OpenShiftClient should be able to
generate + Apply resources based upon project request name, description, display name,
requesting user and admin user. It should create the following resources:

- Project (actual project to be created)
- RoleBinding system:deployers
- RoleBinding system:image-builders
- RoleBinding system:image-pullers
- RoleBinding admin
  • Loading branch information
rohanKanojia committed Jul 31, 2020
1 parent 14cae94 commit 5a057ef
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,7 @@
* Fix #2292: Update createOrReplace to do replace when create fails with conflict

#### New Features
* Fix #2311: Add Support for creating bootstrap project template
* Fix #2287: Add support for V1 and V1Beta1 CustomResourceDefinition
* Fix #2319: Create Config without using auto-configure functionality or setting env variables

Expand Down
Expand Up @@ -16,8 +16,11 @@

package io.fabric8.openshift.client.server.mock;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.Status;
import io.fabric8.kubernetes.api.model.StatusBuilder;
import io.fabric8.kubernetes.api.model.rbac.RoleBindingBuilder;
import io.fabric8.openshift.api.model.ProjectBuilder;
import io.fabric8.openshift.api.model.ProjectRequest;
import io.fabric8.openshift.api.model.ProjectRequestBuilder;
import io.fabric8.openshift.client.OpenShiftClient;
Expand All @@ -26,6 +29,9 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;

import java.net.HttpURLConnection;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

Expand Down Expand Up @@ -58,4 +64,107 @@ public void testCreate() {
assertNotNull(result);
assertEquals(req1, result);
}

@Test
void testCreateUsingParameters() {
// Given
String name = "test-project";
String displayName = "test-project";
String description = "test project";
String requestingUser = "request-user";
String adminUser = "admin-user";
server.expect().post().withPath("/apis/project.openshift.io/v1/projects")
.andReturn(HttpURLConnection.HTTP_CREATED, new ProjectBuilder()
.withNewMetadata()
.addToAnnotations("openshift.io/description", description)
.addToAnnotations("openshift.io/display-name", displayName)
.addToAnnotations("openshift.io/requester", requestingUser)
.withName("test-project")
.endMetadata()
.build()).once();
server.expect().post().withPath("/apis/rbac.authorization.k8s.io/v1/namespaces/test-project/rolebindings")
.andReturn(HttpURLConnection.HTTP_CREATED, new RoleBindingBuilder()
.withNewMetadata()
.addToAnnotations("openshift.io/description", "Allows all pods in this namespace to pull images from this namespace. It is auto-managed by a controller; remove subjects to disable.")
.withName("system:image-pullers")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole")
.withName("system:image-puller")
.endRoleRef()
.addNewSubject()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("Group")
.withName("system:serviceaccounts:" + name)
.endSubject()
.build()).once();
server.expect().post().withPath("/apis/rbac.authorization.k8s.io/v1/namespaces/test-project/rolebindings")
.andReturn(HttpURLConnection.HTTP_CREATED, new RoleBindingBuilder()
.withNewMetadata()
.addToAnnotations("openshift.io/description", "Allows builds in this namespace to push images to" +
"this namespace. It is auto-managed by a controller; remove subjects to disable.")
.withName("system:image-builders")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole")
.withName("system:image-builder")
.endRoleRef()
.addNewSubject()
.withKind("ServiceAccount")
.withName("builder")
.withNamespace(name)
.endSubject()
.build()).once();
server.expect().post().withPath("/apis/rbac.authorization.k8s.io/v1/namespaces/test-project/rolebindings")
.andReturn(HttpURLConnection.HTTP_CREATED, new RoleBindingBuilder()
.withNewMetadata()
.addToAnnotations("openshift.io/description", " Allows deploymentconfigs in this namespace to rollout" +
" pods in this namespace. It is auto-managed by a controller; remove subjects" +
" to disable.")
.withName("system:deployers")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole")
.withName("system:deployer")
.endRoleRef()
.addNewSubject()
.withKind("ServiceAccount")
.withName("deployer")
.withNamespace(name)
.endSubject()
.build()).once();
server.expect().post().withPath("/apis/rbac.authorization.k8s.io/v1/namespaces/test-project/rolebindings")
.andReturn(HttpURLConnection.HTTP_CREATED, new RoleBindingBuilder()
.withNewMetadata()
.withName("admin")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole")
.withName("admin")
.endRoleRef()
.addNewSubject()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("User")
.withName(adminUser)
.endSubject()
.build()).once();


OpenShiftClient client = server.getOpenshiftClient();

// When
List<HasMetadata> result = client.projectrequests().create(name, description, displayName, adminUser, requestingUser);

// Then
assertNotNull(result);
assertEquals(5, result.size());
}
}
Expand Up @@ -15,15 +15,27 @@
*/
package io.fabric8.openshift.client.dsl;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.Status;
import io.fabric8.kubernetes.client.dsl.Createable;
import io.fabric8.kubernetes.client.dsl.Listable;
import io.fabric8.openshift.api.model.DoneableProjectRequest;
import io.fabric8.openshift.api.model.ProjectRequest;

import java.util.List;

public interface ProjectRequestOperation extends
Createable<ProjectRequest, ProjectRequest, DoneableProjectRequest>,
Listable<Status> {


/**
* Creating Bootstrap Project Template
*
* @param name project name
* @param description project description
* @param displayName project display name
* @param adminUser project admin user
* @param requestingUser project requesting user
* @return list of items created
*/
List<HasMetadata> create(String name, String description, String displayName, String adminUser, String requestingUser);
}
Expand Up @@ -15,11 +15,17 @@
*/
package io.fabric8.openshift.client.dsl.internal;

import io.fabric8.kubernetes.api.model.DeletionPropagation;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.ListOptions;
import io.fabric8.kubernetes.api.model.ListOptionsBuilder;
import io.fabric8.kubernetes.api.model.rbac.RoleBinding;
import io.fabric8.kubernetes.api.model.rbac.RoleBindingBuilder;
import io.fabric8.kubernetes.client.dsl.base.OperationContext;
import io.fabric8.kubernetes.client.utils.URLUtils;
import io.fabric8.kubernetes.client.dsl.internal.NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl;
import io.fabric8.kubernetes.client.utils.Utils;
import io.fabric8.openshift.api.model.Project;
import io.fabric8.openshift.api.model.ProjectBuilder;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
Expand All @@ -34,13 +40,21 @@
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static io.fabric8.openshift.client.OpenShiftAPIGroups.PROJECT;

// TODO: Check why this class does not extend OpenshiftOperation, then the getRoot method can be removed
public class ProjectRequestsOperationImpl extends OperationSupport implements ProjectRequestOperation {

public static final String OPENSHIFT_IO_DESCRIPTION_ANNOTATION = "openshift.io/description";
public static final String OPENSHIFT_IO_DISPLAY_NAME_ANNOTATION = "openshift.io/display-name";
public static final String OPENSHIFT_IO_REQUESTER_ANNOTATION = "openshift.io/requester";
public static final String RBAC_AUTHORIZATION_APIGROUP = "rbac.authorization.k8s.io";
public static final String CLUSTER_ROLE = "ClusterRole";

public ProjectRequestsOperationImpl(OkHttpClient client, OpenShiftConfig config) {
this(new OperationContext().withOkhttpClient(client).withConfig(config));
}
Expand Down Expand Up @@ -165,4 +179,114 @@ public Status list(ListOptions listOptions) {
public ProjectRequest getItem() {
return (ProjectRequest) context.getItem();
}

@Override
public List<HasMetadata> create(String name, String description, String displayName, String adminUser, String requestingUser) {
List<HasMetadata> result = new ArrayList<>();
Project project = getProject(name, description, displayName, requestingUser);
List<HasMetadata> projectRoleBindings = getNewProjectRoleBindings(name, adminUser);

// Create Project
ProjectOperationsImpl projectOperations = new ProjectOperationsImpl(client, OpenShiftConfig.wrap(config));
result.add(projectOperations.create(project));

// Create Role Bindings
NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl listOp = new NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl(client, config, getNamespace(), null, false, false, new ArrayList<>(), projectRoleBindings, null, DeletionPropagation.BACKGROUND, true) {};
result.addAll(listOp.createOrReplace());

return result;
}

private Project getProject(String name, String description, String displayName, String requestingUser) {
return new ProjectBuilder()
.withNewMetadata()
.addToAnnotations(OPENSHIFT_IO_DESCRIPTION_ANNOTATION, description)
.addToAnnotations(OPENSHIFT_IO_DISPLAY_NAME_ANNOTATION, displayName)
.addToAnnotations(OPENSHIFT_IO_REQUESTER_ANNOTATION, requestingUser)
.withName(name)
.endMetadata()
.build();
}

private List<HasMetadata> getNewProjectRoleBindings(String name, String adminUser) {
RoleBinding roleBindingPuller = new RoleBindingBuilder()
.withNewMetadata()
.addToAnnotations(OPENSHIFT_IO_DESCRIPTION_ANNOTATION, "Allows all pods in this namespace to pull images from this namespace. It is auto-managed by a controller; remove subjects to disable.")
.withName("system:image-pullers")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup(RBAC_AUTHORIZATION_APIGROUP)
.withKind(CLUSTER_ROLE)
.withName("system:image-puller")
.endRoleRef()
.addNewSubject()
.withApiGroup(RBAC_AUTHORIZATION_APIGROUP)
.withKind("Group")
.withName("system:serviceaccounts:" + name)
.endSubject()
.build();
RoleBinding roleBindingBuilder = new RoleBindingBuilder()
.withNewMetadata()
.addToAnnotations(OPENSHIFT_IO_DESCRIPTION_ANNOTATION, "Allows builds in this namespace to push images to" +
"this namespace. It is auto-managed by a controller; remove subjects to disable.")
.withName("system:image-builders")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup(RBAC_AUTHORIZATION_APIGROUP)
.withKind(CLUSTER_ROLE)
.withName("system:image-builder")
.endRoleRef()
.addNewSubject()
.withKind("ServiceAccount")
.withName("builder")
.withNamespace(name)
.endSubject()
.build();
RoleBinding roleBindingDeployer = new RoleBindingBuilder()
.withNewMetadata()
.addToAnnotations(OPENSHIFT_IO_DESCRIPTION_ANNOTATION, " Allows deploymentconfigs in this namespace to rollout" +
" pods in this namespace. It is auto-managed by a controller; remove subjects" +
" to disable.")
.withName("system:deployers")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup(RBAC_AUTHORIZATION_APIGROUP)
.withKind(CLUSTER_ROLE)
.withName("system:deployer")
.endRoleRef()
.addNewSubject()
.withKind("ServiceAccount")
.withName("deployer")
.withNamespace(name)
.endSubject()
.build();

RoleBinding roleBindingAdmin = new RoleBindingBuilder()
.withNewMetadata()
.withName("admin")
.withNamespace(name)
.endMetadata()
.withNewRoleRef()
.withApiGroup(RBAC_AUTHORIZATION_APIGROUP)
.withKind(CLUSTER_ROLE)
.withName("admin")
.endRoleRef()
.addNewSubject()
.withApiGroup(RBAC_AUTHORIZATION_APIGROUP)
.withKind("User")
.withName(adminUser)
.endSubject()
.build();

List<HasMetadata> resources = new ArrayList<>();
resources.add(roleBindingPuller);
resources.add(roleBindingBuilder);
resources.add(roleBindingDeployer);
resources.add(roleBindingAdmin);

return resources;
}
}

0 comments on commit 5a057ef

Please sign in to comment.