CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-fabric8--kubernetes-client-project

Java client for Kubernetes and OpenShift providing access to full REST APIs via a fluent DSL

Pending
Overview
Eval results
Files

project-operations.mddocs/

Project Operations

This document covers OpenShift project operations, including project creation with role bindings, project requests, and project management.

Core Imports

import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.client.dsl.ProjectOperation;
import io.fabric8.openshift.client.dsl.ProjectRequestOperation;
import io.fabric8.kubernetes.api.model.Namespace;
import io.fabric8.kubernetes.api.model.NamespaceList;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.Resource;

Project Operations

OpenShift projects extend Kubernetes namespaces with additional OpenShift-specific functionality, including role-based access control and resource quotas.

Basic Project Operations

// List all projects (equivalent to namespaces with OpenShift metadata)
List<Namespace> projects = client.projects().list().getItems();

// Get a specific project
Namespace project = client.projects()
    .withName("my-project")
    .get();

// Check if project exists
boolean exists = client.projects()
    .withName("my-project")
    .get() != null;

Creating Projects

// Create a simple project (namespace)
Namespace simpleProject = client.projects()
    .create(new NamespaceBuilder()
        .withNewMetadata()
            .withName("simple-project")
            .addToLabels("type", "development")
        .endMetadata()
        .build());

// Create project with display name and description
Namespace projectWithMetadata = client.projects()
    .create(new NamespaceBuilder()
        .withNewMetadata()
            .withName("my-application")
            .addToAnnotations("openshift.io/display-name", "My Application")
            .addToAnnotations("openshift.io/description", "Development project for my application")
            .addToLabels("environment", "development")
        .endMetadata()
        .build());

Project Creation with Role Bindings

// Create project with automatic role bindings
Namespace projectWithRoles = client.projects()
    .createProjectAndRoleBindings(
        "team-project",                    // project name
        "Team Development Project",        // description
        "Team Project",                    // display name
        "developer-user"                   // admin user
    );

// Create project with multiple administrators
Namespace multiAdminProject = client.projects()
    .createProjectAndRoleBindings(
        "multi-admin-project",
        "Multi-administrator project", 
        "Multi Admin Project",
        "admin-user1,admin-user2"         // comma-separated admin users
    );

Project Deletion and Cleanup

// Delete a project (this will delete the namespace and all resources)
Boolean deleted = client.projects()
    .withName("obsolete-project")
    .delete();

// Delete project with grace period
Boolean gracefullyDeleted = client.projects()
    .withName("project-to-delete")
    .withGracePeriod(30)  // 30 seconds
    .delete();

// Force delete project (immediate deletion)
Boolean forceDeleted = client.projects()
    .withName("stuck-project")
    .withGracePeriod(0)
    .delete();

ProjectRequest Operations

ProjectRequest is used to request the creation of new projects, typically by regular users who don't have cluster-admin privileges.

Creating Project Requests

// Create a project request (for non-admin users)
ProjectRequest projectRequest = new ProjectRequestBuilder()
    .withNewMetadata()
        .withName("requested-project")
    .endMetadata()
    .withDisplayName("Requested Project")
    .withDescription("Project requested by developer")
    .build();

// Submit project request
ProjectRequest submittedRequest = client.projectrequests()
    .create(projectRequest);

// The project request will create a project if the user has permission
Namespace createdProject = client.projects()
    .withName("requested-project")
    .get();

Project Request with Custom Settings

// Project request with detailed metadata
ProjectRequest detailedRequest = new ProjectRequestBuilder()
    .withNewMetadata()
        .withName("detailed-project")
        .addToAnnotations("openshift.io/requester", "john.doe")
    .endMetadata()
    .withDisplayName("Detailed Development Project")
    .withDescription("Comprehensive project for application development")
    .build();

ProjectRequest created = client.projectrequests()
    .create(detailedRequest);

Project Management

Project Monitoring and Status

// Watch project changes
client.projects()
    .watch(new Watcher<Namespace>() {
        @Override
        public void eventReceived(Action action, Namespace project) {
            System.out.println("Project " + action + ": " + 
                project.getMetadata().getName());
                
            String displayName = project.getMetadata().getAnnotations()
                .get("openshift.io/display-name");
            if (displayName != null) {
                System.out.println("  Display Name: " + displayName);
            }
        }
        
        @Override
        public void onClose(WatcherException cause) {
            System.out.println("Project watch closed: " + cause.getMessage());
        }
    });

// Get project status and phase
Namespace project = client.projects()
    .withName("my-project")
    .get();

String phase = project.getStatus().getPhase();  // Active, Terminating
System.out.println("Project phase: " + phase);

Project Metadata Management

// Update project annotations and labels
Namespace updatedProject = client.projects()
    .withName("my-project")
    .edit(project -> new NamespaceBuilder(project)
        .editMetadata()
            .addToAnnotations("openshift.io/display-name", "Updated Display Name")
            .addToAnnotations("openshift.io/description", "Updated description")
            .addToLabels("team", "backend")
            .addToLabels("environment", "production")
        .endMetadata()
        .build());

// Remove annotations
Namespace cleanedProject = client.projects()
    .withName("my-project")
    .edit(project -> new NamespaceBuilder(project)
        .editMetadata()
            .removeFromAnnotations("obsolete-annotation")
        .endMetadata()
        .build());

Project Resource Management

// Get all resources in a project
client.inNamespace("my-project").pods().list();
client.inNamespace("my-project").services().list();
client.inNamespace("my-project").deploymentConfigs().list();
client.inNamespace("my-project").routes().list();

// Count resources in project
int podCount = client.inNamespace("my-project").pods().list().getItems().size();
int serviceCount = client.inNamespace("my-project").services().list().getItems().size();

System.out.println("Project my-project has " + podCount + " pods and " + 
    serviceCount + " services");

Advanced Project Operations

Project Templates and Initialization

// Initialize project with template
public void initializeProjectFromTemplate(String projectName, String templateName) {
    // 1. Create project
    Namespace project = client.projects()
        .createProjectAndRoleBindings(
            projectName,
            "Project created from template " + templateName,
            projectName,
            client.currentUser().getMetadata().getName()
        );
    
    // 2. Apply template
    Template processed = client.templates()
        .inNamespace("openshift")  // Common template namespace
        .withName(templateName)
        .withParameter("PROJECT_NAME", projectName)
        .process();
    
    // 3. Create objects in the new project
    for (HasMetadata object : processed.getObjects()) {
        object.getMetadata().setNamespace(projectName);
        client.resource(object).createOrReplace();
    }
}

Project Access Control

// Add user to project with admin role
RoleBinding adminBinding = new RoleBindingBuilder()
    .withNewMetadata()
        .withName("admin-binding")
        .withNamespace("my-project")
    .endMetadata()
    .withNewRoleRef()
        .withApiGroup("rbac.authorization.k8s.io")
        .withKind("ClusterRole")
        .withName("admin")
    .endRoleRef()
    .addNewSubject()
        .withKind("User")
        .withName("new-admin-user")
        .withApiGroup("rbac.authorization.k8s.io")
    .endSubject()
    .build();

client.rbac().roleBindings()
    .inNamespace("my-project")
    .create(adminBinding);

// Add group to project with view role
RoleBinding viewBinding = new RoleBindingBuilder()
    .withNewMetadata()
        .withName("viewers-binding")
        .withNamespace("my-project")
    .endMetadata()
    .withNewRoleRef()
        .withApiGroup("rbac.authorization.k8s.io")
        .withKind("ClusterRole")
        .withName("view")
    .endRoleRef()
    .addNewSubject()
        .withKind("Group")
        .withName("developers")
        .withApiGroup("rbac.authorization.k8s.io")
    .endSubject()
    .build();

client.rbac().roleBindings()
    .inNamespace("my-project")
    .create(viewBinding);

Project Resource Quotas

// Set resource quota for project
ResourceQuota quota = new ResourceQuotaBuilder()
    .withNewMetadata()
        .withName("project-quota")
        .withNamespace("my-project")
    .endMetadata()
    .withNewSpec()
        .addToHard("requests.cpu", new Quantity("2"))
        .addToHard("requests.memory", new Quantity("4Gi"))
        .addToHard("limits.cpu", new Quantity("4"))
        .addToHard("limits.memory", new Quantity("8Gi"))
        .addToHard("persistentvolumeclaims", new Quantity("10"))
        .addToHard("pods", new Quantity("20"))
        .addToHard("services", new Quantity("10"))
    .endSpec()
    .build();

client.resourceQuotas()
    .inNamespace("my-project")
    .create(quota);

// Check quota usage
ResourceQuota currentQuota = client.resourceQuotas()
    .inNamespace("my-project")
    .withName("project-quota")
    .get();

Map<String, Quantity> used = currentQuota.getStatus().getUsed();
Map<String, Quantity> hard = currentQuota.getStatus().getHard();

System.out.println("CPU usage: " + used.get("requests.cpu") + 
    " / " + hard.get("requests.cpu"));

Project Network Policies

// Create network policy to isolate project
NetworkPolicy isolationPolicy = new NetworkPolicyBuilder()
    .withNewMetadata()
        .withName("deny-all")
        .withNamespace("my-project")
    .endMetadata()
    .withNewSpec()
        .withNewPodSelector()  // Selects all pods
        .endPodSelector()
        .withPolicyTypes("Ingress", "Egress")
        // Empty ingress/egress rules = deny all
    .endSpec()
    .build();

client.network().v1().networkPolicies()
    .inNamespace("my-project")
    .create(isolationPolicy);

// Allow ingress from specific project
NetworkPolicy allowFromProject = new NetworkPolicyBuilder()
    .withNewMetadata()
        .withName("allow-from-frontend")
        .withNamespace("my-project")
    .endMetadata()
    .withNewSpec()
        .withNewPodSelector()
            .addToMatchLabels("app", "backend")
        .endPodSelector()
        .withPolicyTypes("Ingress")
        .addNewIngress()
            .addNewFrom()
                .withNewNamespaceSelector()
                    .addToMatchLabels("name", "frontend-project")
                .endNamespaceSelector()
            .endFrom()
        .endIngress()
    .endSpec()
    .build();

client.network().v1().networkPolicies()
    .inNamespace("my-project")
    .create(allowFromProject);

Usage Examples

Complete Project Setup Example

import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.rbac.*;

public class ProjectManager {
    private final OpenShiftClient client;
    
    public ProjectManager(OpenShiftClient client) {
        this.client = client;
    }
    
    public void setupCompleteProject(String projectName, String displayName,
                                   String description, String adminUser,
                                   List<String> developers, List<String> viewers) {
        
        // 1. Create project with initial admin
        System.out.println("Creating project: " + projectName);
        Namespace project = client.projects()
            .createProjectAndRoleBindings(projectName, description, displayName, adminUser);
        
        // 2. Set up additional role bindings
        setupProjectRoles(projectName, developers, viewers);
        
        // 3. Create resource quota
        setupResourceQuota(projectName);
        
        // 4. Create network policies
        setupNetworkPolicies(projectName);
        
        // 5. Create default pull secret
        setupPullSecrets(projectName);
        
        System.out.println("Project setup completed: " + projectName);
    }
    
    private void setupProjectRoles(String projectName, List<String> developers, 
                                  List<String> viewers) {
        // Add developers with edit role
        if (!developers.isEmpty()) {
            RoleBinding devBinding = new RoleBindingBuilder()
                .withNewMetadata()
                    .withName("developers")
                    .withNamespace(projectName)
                .endMetadata()
                .withNewRoleRef()
                    .withApiGroup("rbac.authorization.k8s.io")
                    .withKind("ClusterRole")
                    .withName("edit")
                .endRoleRef()
                .build();
                
            for (String dev : developers) {
                devBinding.getSubjects().add(new SubjectBuilder()
                    .withKind("User")
                    .withName(dev)
                    .withApiGroup("rbac.authorization.k8s.io")
                    .build());
            }
            
            client.rbac().roleBindings()
                .inNamespace(projectName)
                .create(devBinding);
        }
        
        // Add viewers with view role
        if (!viewers.isEmpty()) {
            RoleBinding viewBinding = new RoleBindingBuilder()
                .withNewMetadata()
                    .withName("viewers")
                    .withNamespace(projectName)
                .endMetadata()
                .withNewRoleRef()
                    .withApiGroup("rbac.authorization.k8s.io")
                    .withKind("ClusterRole")
                    .withName("view")
                .endRoleRef()
                .build();
                
            for (String viewer : viewers) {
                viewBinding.getSubjects().add(new SubjectBuilder()
                    .withKind("User")
                    .withName(viewer)
                    .withApiGroup("rbac.authorization.k8s.io")
                    .build());
            }
            
            client.rbac().roleBindings()
                .inNamespace(projectName)
                .create(viewBinding);
        }
    }
    
    private void setupResourceQuota(String projectName) {
        ResourceQuota quota = new ResourceQuotaBuilder()
            .withNewMetadata()
                .withName("compute-quota")
                .withNamespace(projectName)
            .endMetadata()
            .withNewSpec()
                .addToHard("requests.cpu", new Quantity("4"))
                .addToHard("requests.memory", new Quantity("8Gi"))
                .addToHard("limits.cpu", new Quantity("8"))
                .addToHard("limits.memory", new Quantity("16Gi"))
                .addToHard("persistentvolumeclaims", new Quantity("20"))
                .addToHard("pods", new Quantity("50"))
                .addToHard("services", new Quantity("20"))
                .addToHard("secrets", new Quantity("50"))
                .addToHard("configmaps", new Quantity("50"))
            .endSpec()
            .build();
            
        client.resourceQuotas()
            .inNamespace(projectName)
            .create(quota);
    }
    
    private void setupNetworkPolicies(String projectName) {
        // Allow ingress from OpenShift system namespaces
        NetworkPolicy allowSystem = new NetworkPolicyBuilder()
            .withNewMetadata()
                .withName("allow-from-openshift")
                .withNamespace(projectName)
            .endMetadata()
            .withNewSpec()
                .withNewPodSelector()  // All pods
                .endPodSelector()
                .withPolicyTypes("Ingress")
                .addNewIngress()
                    .addNewFrom()
                        .withNewNamespaceSelector()
                            .addToMatchLabels("name", "openshift-ingress")
                        .endNamespaceSelector()
                    .endFrom()
                .endIngress()
                .addNewIngress()
                    .addNewFrom()
                        .withNewNamespaceSelector()
                            .addToMatchLabels("name", "openshift-monitoring")
                        .endNamespaceSelector()
                    .endFrom()
                .endIngress()
            .endSpec()
            .build();
            
        client.network().v1().networkPolicies()
            .inNamespace(projectName)
            .create(allowSystem);
    }
    
    private void setupPullSecrets(String projectName) {
        // Link default pull secret to default service account
        ServiceAccount defaultSA = client.serviceAccounts()
            .inNamespace(projectName)
            .withName("default")
            .get();
            
        if (defaultSA != null) {
            client.serviceAccounts()
                .inNamespace(projectName)
                .withName("default")
                .edit(sa -> new ServiceAccountBuilder(sa)
                    .addNewImagePullSecret()
                        .withName("default-dockercfg-secret")
                    .endImagePullSecret()
                    .build());
        }
    }
    
    public void cleanupProject(String projectName) {
        System.out.println("Cleaning up project: " + projectName);
        
        // Get project first to ensure it exists
        Namespace project = client.projects().withName(projectName).get();
        if (project == null) {
            System.out.println("Project not found: " + projectName);
            return;
        }
        
        // Delete project (this cascades to all resources)
        Boolean deleted = client.projects()
            .withName(projectName)
            .delete();
            
        if (deleted) {
            // Wait for project deletion
            client.projects()
                .withName(projectName)
                .waitUntilCondition(Objects::isNull, 5, TimeUnit.MINUTES);
            
            System.out.println("Project deleted: " + projectName);
        } else {
            System.err.println("Failed to delete project: " + projectName);
        }
    }
}

Types

ProjectOperation

public interface ProjectOperation extends NonNamespaceOperation<Namespace, NamespaceList, Resource<Namespace>> {
    
    /**
     * Create a new project with role bindings for the specified user.
     * 
     * @param name project name
     * @param description project description  
     * @param displayName project display name
     * @param adminUser user to grant admin access
     * @return created Namespace (project)
     */
    Namespace createProjectAndRoleBindings(String name, String description, 
                                         String displayName, String adminUser);
}

ProjectRequestOperation

public interface ProjectRequestOperation extends 
    InOutCreateable<ProjectRequest, ProjectRequest> {
    // Inherits create methods for ProjectRequest objects
}

ProjectRequest

public class ProjectRequest implements HasMetadata {
    public ObjectMeta getMetadata();
    public String getDisplayName();
    public String getDescription();
}

Project-related Kubernetes Types

// Projects are represented as Kubernetes Namespaces with additional annotations
public class Namespace implements HasMetadata {
    public ObjectMeta getMetadata();
    public NamespaceSpec getSpec();
    public NamespaceStatus getStatus();
}

public class NamespaceSpec {
    public List<String> getFinalizers();
}

public class NamespaceStatus {
    public String getPhase();  // Active, Terminating
    public List<NamespaceCondition> getConditions();
}

Install with Tessl CLI

npx tessl i tessl/maven-io-fabric8--kubernetes-client-project

docs

api-group-operations.md

authorization-reviews.md

build-operations.md

client-configuration.md

deployment-operations.md

image-operations.md

index.md

network-operations.md

project-operations.md

template-operations.md

user-security.md

tile.json