Java client for Kubernetes and OpenShift providing access to full REST APIs via a fluent DSL
—
This document covers OpenShift image management operations, including image streams, image stream tags, image imports, and container registry operations.
import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.Image;
import io.fabric8.openshift.api.model.ImageList;
import io.fabric8.openshift.api.model.ImageStream;
import io.fabric8.openshift.api.model.ImageStreamList;
import io.fabric8.openshift.api.model.ImageStreamTag;
import io.fabric8.openshift.api.model.ImageStreamTagList;
import io.fabric8.openshift.api.model.ImageTag;
import io.fabric8.openshift.api.model.ImageTagList;
import io.fabric8.openshift.api.model.ImageStreamImport;
import io.fabric8.openshift.api.model.ImageStreamMapping;
import io.fabric8.openshift.api.model.ImageStreamImage;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.NamespacedInOutCreateable;// List all images in the cluster
ImageList images = client.images().list();
// Get a specific image by name
Image image = client.images()
.withName("sha256:abc123...")
.get();
// List images with label selector
ImageList labeledImages = client.images()
.withLabel("version", "latest")
.list();// Get image metadata
Image image = client.images()
.withName("sha256:abc123...")
.get();
String dockerImageReference = image.getDockerImageReference();
ObjectMeta metadata = image.getDockerImageMetadata();
List<String> layers = image.getDockerImageLayers();
String manifest = image.getDockerImageManifest();// List all image streams in a namespace
ImageStreamList imageStreams = client.imageStreams()
.inNamespace("my-project")
.list();
// Get a specific image stream
ImageStream imageStream = client.imageStreams()
.inNamespace("my-project")
.withName("my-app")
.get();
// Create a new image stream
ImageStream newImageStream = new ImageStreamBuilder()
.withNewMetadata()
.withName("my-new-app")
.withNamespace("my-project")
.addToLabels("app", "my-new-app")
.endMetadata()
.withNewSpec()
.addNewTag()
.withName("latest")
.withNewFrom()
.withKind("DockerImage")
.withName("registry.example.com/my-app:latest")
.endFrom()
.endTag()
.endSpec()
.build();
ImageStream created = client.imageStreams()
.inNamespace("my-project")
.create(newImageStream);// Add a new tag to an image stream
ImageStream updated = client.imageStreams()
.inNamespace("my-project")
.withName("my-app")
.edit(is -> new ImageStreamBuilder(is)
.editSpec()
.addNewTag()
.withName("v2.0")
.withNewFrom()
.withKind("DockerImage")
.withName("registry.example.com/my-app:2.0.0")
.endFrom()
.endTag()
.endSpec()
.build());
// Remove a tag from an image stream
ImageStream tagRemoved = client.imageStreams()
.inNamespace("my-project")
.withName("my-app")
.edit(is -> new ImageStreamBuilder(is)
.editSpec()
.removeFromTags(is.getSpec().getTags().stream()
.filter(tag -> "old-tag".equals(tag.getName()))
.findFirst()
.orElse(null))
.endSpec()
.build());// Get image stream status
ImageStream imageStream = client.imageStreams()
.inNamespace("my-project")
.withName("my-app")
.get();
List<NamedTagEventList> tags = imageStream.getStatus().getTags();
for (NamedTagEventList tag : tags) {
System.out.println("Tag: " + tag.getTag());
for (TagEvent event : tag.getItems()) {
System.out.println(" Image: " + event.getImage());
System.out.println(" Created: " + event.getCreated());
}
}// Get a specific image stream tag
ImageStreamTag imageStreamTag = client.imageStreamTags()
.inNamespace("my-project")
.withName("my-app:latest")
.get();
// List all image stream tags in namespace
ImageStreamTagList allTags = client.imageStreamTags()
.inNamespace("my-project")
.list();
// Create or update an image stream tag
ImageStreamTag newTag = new ImageStreamTagBuilder()
.withNewMetadata()
.withName("my-app:stable")
.withNamespace("my-project")
.endMetadata()
.withNewTag()
.withNewFrom()
.withKind("ImageStreamTag")
.withName("my-app:latest")
.endFrom()
.endTag()
.build();
ImageStreamTag created = client.imageStreamTags()
.inNamespace("my-project")
.create(newTag);// Get tag information
ImageStreamTag tag = client.imageStreamTags()
.inNamespace("my-project")
.withName("my-app:latest")
.get();
Image tagImage = tag.getImage();
String dockerImageReference = tag.getTag().getFrom().getName();
List<TagCondition> conditions = tag.getTag().getConditions();// List image tags in namespace
ImageTagList imageTags = client.imageTags()
.inNamespace("my-project")
.list();
// Get specific image tag
ImageTag imageTag = client.imageTags()
.inNamespace("my-project")
.withName("my-app:latest")
.get();
// Create image tag
ImageTag newImageTag = new ImageTagBuilder()
.withNewMetadata()
.withName("my-app:production")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.withNewFrom()
.withKind("ImageStreamTag")
.withName("my-app:latest")
.endFrom()
.endSpec()
.build();
ImageTag created = client.imageTags()
.inNamespace("my-project")
.create(newImageTag);// Import external image into image stream
ImageStreamImport imageImport = new ImageStreamImportBuilder()
.withNewMetadata()
.withName("my-app")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.withImport(true)
.withNewRepository()
.withNewFrom()
.withKind("DockerImage")
.withName("registry.example.com/my-app:latest")
.endFrom()
.withNewImportPolicy()
.withInsecure(false)
.withScheduled(true)
.endImportPolicy()
.endRepository()
.addNewImage()
.withNewFrom()
.withKind("DockerImage")
.withName("registry.example.com/my-app:v1.0")
.endFrom()
.withNewTo()
.withName("v1.0")
.endTo()
.withNewImportPolicy()
.withInsecure(false)
.endImportPolicy()
.endImage()
.endSpec()
.build();
ImageStreamImport result = client.imageStreamImports()
.inNamespace("my-project")
.create(imageImport);// Create image stream mapping (typically used by registry)
ImageStreamMapping mapping = new ImageStreamMappingBuilder()
.withNewMetadata()
.withName("my-app")
.withNamespace("my-project")
.endMetadata()
.withNewImage()
.withDockerImageReference("registry.example.com/my-app@sha256:abc123...")
.withNewMetadata()
.withName("sha256:abc123...")
.endMetadata()
.endImage()
.withTag("latest")
.build();
ImageStreamMapping created = client.imageStreamMappings()
.inNamespace("my-project")
.create(mapping);// Get image stream image (read-only)
ImageStreamImage imageStreamImage = client.imageStreamImages()
.inNamespace("my-project")
.withName("my-app@sha256:abc123...")
.get();
String dockerImageReference = imageStreamImage.getImage().getDockerImageReference();
ObjectMeta imageMetadata = imageStreamImage.getImage().getDockerImageMetadata();// Watch image stream changes
client.imageStreams()
.inNamespace("my-project")
.withName("my-app")
.watch(new Watcher<ImageStream>() {
@Override
public void eventReceived(Action action, ImageStream imageStream) {
System.out.println("ImageStream " + action + ": " +
imageStream.getMetadata().getName());
if (imageStream.getStatus() != null && imageStream.getStatus().getTags() != null) {
imageStream.getStatus().getTags().forEach(tag ->
System.out.println(" Tag: " + tag.getTag() +
" (" + tag.getItems().size() + " images)"));
}
}
@Override
public void onClose(WatcherException cause) {
System.out.println("Watch closed: " + cause.getMessage());
}
});// Create image pull secret
Secret pullSecret = new SecretBuilder()
.withNewMetadata()
.withName("registry-secret")
.withNamespace("my-project")
.endMetadata()
.withType("kubernetes.io/dockerconfigjson")
.addToData(".dockerconfigjson",
Base64.getEncoder().encodeToString(dockerConfig.getBytes()))
.build();
client.secrets()
.inNamespace("my-project")
.create(pullSecret);
// Link pull secret to image stream
ImageStream linked = client.imageStreams()
.inNamespace("my-project")
.withName("my-app")
.edit(is -> new ImageStreamBuilder(is)
.editSpec()
.addNewTag()
.withName("secure")
.withNewFrom()
.withKind("DockerImage")
.withName("private-registry.com/my-app:latest")
.endFrom()
.withNewReferencePolicy()
.withType("Local")
.endReferencePolicy()
.withNewImportPolicy()
.withInsecure(false)
.endImportPolicy()
.endTag()
.endSpec()
.build());// Get images that can be pruned (using image pruner configuration)
// This typically requires cluster admin privileges
List<Image> allImages = client.images().list().getItems();
// Filter images for potential pruning based on age and usage
long cutoffTime = System.currentTimeMillis() - (30 * 24 * 60 * 60 * 1000L); // 30 days
List<Image> candidatesForPruning = allImages.stream()
.filter(image -> {
String created = image.getDockerImageMetadata().getCreated();
// Parse created timestamp and compare with cutoff
return parseTimestamp(created) < cutoffTime;
})
.collect(Collectors.toList());import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.*;
public class ImageManager {
private final OpenShiftClient client;
public ImageManager(OpenShiftClient client) {
this.client = client;
}
public void setupApplicationImages(String namespace, String appName,
String externalImage) {
// 1. Create image stream
ImageStream imageStream = createImageStream(namespace, appName);
// 2. Import external image
importExternalImage(namespace, appName, externalImage, "latest");
// 3. Create additional tags
createTag(namespace, appName, "stable", "latest");
// 4. Monitor import status
waitForImageImport(namespace, appName, "latest");
System.out.println("Image setup completed for " + appName);
}
private ImageStream createImageStream(String namespace, String appName) {
ImageStream existing = client.imageStreams()
.inNamespace(namespace)
.withName(appName)
.get();
if (existing != null) {
return existing;
}
return client.imageStreams()
.inNamespace(namespace)
.create(new ImageStreamBuilder()
.withNewMetadata()
.withName(appName)
.withNamespace(namespace)
.addToLabels("app", appName)
.endMetadata()
.withNewSpec()
.withLookupPolicy(new ImageLookupPolicyBuilder()
.withLocal(true)
.build())
.endSpec()
.build());
}
private void importExternalImage(String namespace, String appName,
String externalImage, String tag) {
ImageStreamImport imageImport = new ImageStreamImportBuilder()
.withNewMetadata()
.withName(appName)
.withNamespace(namespace)
.endMetadata()
.withNewSpec()
.withImport(true)
.addNewImage()
.withNewFrom()
.withKind("DockerImage")
.withName(externalImage)
.endFrom()
.withNewTo()
.withName(tag)
.endTo()
.withNewImportPolicy()
.withInsecure(false)
.withScheduled(false)
.endImportPolicy()
.endImage()
.endSpec()
.build();
ImageStreamImport result = client.imageStreamImports()
.inNamespace(namespace)
.create(imageImport);
// Check import status
if (result.getStatus() != null && result.getStatus().getImages() != null) {
result.getStatus().getImages().forEach(imageStatus -> {
if (imageStatus.getStatus().getStatus().equals("Success")) {
System.out.println("Successfully imported: " +
imageStatus.getTag());
} else {
System.err.println("Failed to import " + imageStatus.getTag() +
": " + imageStatus.getStatus().getMessage());
}
});
}
}
private void createTag(String namespace, String appName,
String newTag, String sourceTag) {
client.imageStreamTags()
.inNamespace(namespace)
.create(new ImageStreamTagBuilder()
.withNewMetadata()
.withName(appName + ":" + newTag)
.withNamespace(namespace)
.endMetadata()
.withNewTag()
.withNewFrom()
.withKind("ImageStreamTag")
.withName(appName + ":" + sourceTag)
.withNamespace(namespace)
.endFrom()
.endTag()
.build());
}
private void waitForImageImport(String namespace, String appName, String tag) {
client.imageStreams()
.inNamespace(namespace)
.withName(appName)
.waitUntilCondition(imageStream -> {
if (imageStream.getStatus() == null ||
imageStream.getStatus().getTags() == null) {
return false;
}
return imageStream.getStatus().getTags().stream()
.anyMatch(namedTag ->
tag.equals(namedTag.getTag()) &&
!namedTag.getItems().isEmpty());
}, 5, TimeUnit.MINUTES);
}
public void promoteImage(String namespace, String appName,
String fromTag, String toTag) {
// Promote image from one tag to another
ImageStreamTag sourceTag = client.imageStreamTags()
.inNamespace(namespace)
.withName(appName + ":" + fromTag)
.get();
if (sourceTag == null) {
throw new RuntimeException("Source tag not found: " + fromTag);
}
client.imageStreamTags()
.inNamespace(namespace)
.createOrReplace(new ImageStreamTagBuilder()
.withNewMetadata()
.withName(appName + ":" + toTag)
.withNamespace(namespace)
.endMetadata()
.withNewTag()
.withNewFrom()
.withKind("ImageStreamImage")
.withName(appName + "@" + sourceTag.getImage().getName())
.withNamespace(namespace)
.endFrom()
.endTag()
.build());
System.out.println("Promoted " + fromTag + " to " + toTag);
}
}public class Image implements HasMetadata {
public ObjectMeta getMetadata();
public String getDockerImageReference();
public ObjectMeta getDockerImageMetadata();
public List<ImageLayer> getDockerImageLayers();
public String getDockerImageManifest();
public String getDockerImageManifestMediaType();
public ImageSignature getSignatures();
}
public class ImageLayer {
public String getName();
public Long getSize();
public String getMediaType();
}public class ImageStream implements HasMetadata {
public ObjectMeta getMetadata();
public ImageStreamSpec getSpec();
public ImageStreamStatus getStatus();
}
public class ImageStreamSpec {
public ImageLookupPolicy getLookupPolicy();
public List<TagReference> getTags();
}
public class ImageStreamStatus {
public String getDockerImageRepository();
public String getPublicDockerImageRepository();
public List<NamedTagEventList> getTags();
}
public class TagReference {
public String getName();
public ObjectReference getFrom();
public TagReferencePolicy getReferencePolicy();
public String getGeneration();
public TagImportPolicy getImportPolicy();
}public class ImageStreamTag implements HasMetadata {
public ObjectMeta getMetadata();
public TagReference getTag();
public String getGeneration();
public List<TagCondition> getConditions();
public Image getImage();
}
public class TagCondition {
public String getType(); // ImportSuccess
public String getStatus(); // True, False, Unknown
public String getLastTransitionTime();
public String getReason();
public String getMessage();
public String getGeneration();
}public class ImageStreamImport implements HasMetadata {
public ObjectMeta getMetadata();
public ImageStreamImportSpec getSpec();
public ImageStreamImportStatus getStatus();
}
public class ImageStreamImportSpec {
public Boolean getImport();
public RepositoryImportSpec getRepository();
public List<ImageImportSpec> getImages();
}
public class ImageImportSpec {
public ObjectReference getFrom();
public LocalObjectReference getTo();
public TagImportPolicy getImportPolicy();
public Boolean getIncludeManifest();
public TagReferencePolicy getReferencePolicy();
}Install with Tessl CLI
npx tessl i tessl/maven-io-fabric8--kubernetes-client-project